Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51117262 authored by Jim Miller's avatar Jim Miller
Browse files

Handle DevicePolicyManagement and safe mode when inflating widgets

Bug 7459120
Bug 7444159
Bug 7444016

Change-Id: I7966ec510da8113ac571b5a4b9dc48dd291396e8
Conflicts:
	policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
parent 475255bf
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -3228,6 +3228,13 @@ public final class Settings {
        public static final String LOCK_SCREEN_APPWIDGET_IDS =
            "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
+31 −0
Original line number Diff line number Diff line
@@ -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,
@@ -1326,4 +1347,14 @@ public class LockPatternUtils {
        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;
    }

}
+149 −69
Original line number Diff line number Diff line
@@ -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 {
            if (updateDbIfFailed) {
                Log.w(TAG, "AppWidgetInfo for app widget id " + appId + " was null, deleting");
                mAppWidgetHost.deleteAppWidgetId(appId);
                mLockPatternUtils.removeAppWidget(appId);
            }
            return false;
        }
    }
@@ -885,16 +934,9 @@ 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);
        if (!mSafeModeEnabled && !widgetsDisabledByDpm()) {
            View addWidget = inflater.inflate(R.layout.keyguard_add_widget, this, false);
            mAppWidgetContainer.addWidget(addWidget);
        if (mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
            View cameraWidget =
                    CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher);
            if (cameraWidget != null) {
                mAppWidgetContainer.addWidget(cameraWidget);
            }
        }

            View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
            addWidgetButton.setOnClickListener(new OnClickListener() {
                @Override
@@ -907,6 +949,19 @@ public class KeyguardHostView extends KeyguardViewBase {
                    }
                }
            });
        }

        // 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) {
                mAppWidgetContainer.addWidget(cameraWidget);
            }
        }

        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");
        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();
            final int insertPageIndex = getInsertPageIndex();

            Resources res = getContext().getResources();
            ComponentName defaultAppWidget = new ComponentName(
                    res.getString(R.string.widget_default_package_name),
                    res.getString(R.string.widget_default_class_name));
            final boolean userAddedWidgetsEnabled = !widgetsDisabledByDpm();
            boolean addedDefaultAppWidget = false;

            // 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);
            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(addPageIndex + 1), addPageIndex + 1);
                        mAppWidgetContainer.getChildAt(insertPageIndex), insertPageIndex);
            }
        }
    }

@@ -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.
+1 −0
Original line number Diff line number Diff line
@@ -260,4 +260,5 @@ public abstract class KeyguardViewBase extends FrameLayout {
            KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
        mViewMediatorCallback = viewMediatorCallback;
    }

}
+18 −29
Original line number Diff line number Diff line
@@ -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,33 +478,29 @@ 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]--;
            }
        }
    }

    /*
     * Special widgets
     */
    boolean isAddWidgetPageVisible() {
        // TODO: Make proper test once we decide whether the add-page is always showing
        return true;
            while (range[0] < range[1] && !isWidgetPage(range[0])) {
                range[0]++;
            }
    boolean isMusicWidgetVisible() {
        return mViewStateManager.getTransportState() != KeyguardViewStateManager.TRANSPORT_GONE;
        }
    boolean isCameraWidgetVisible() {
        return mCameraWidgetEnabled;
    }

    protected void reorderStarting() {
@@ -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) {