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

Commit 4c7d3506 authored by Jean-Baptiste Queru's avatar Jean-Baptiste Queru
Browse files

Merge policy from frameworks/policies/base

Change-Id: Ieca556a1e9ef62f6450aac1dfd33e8c180e7eeeb
parents ba56799f f97c3434
Loading
Loading
Loading
Loading

policy/Android.mk

0 → 100644
+13 −0
Original line number Diff line number Diff line
LOCAL_PATH:= $(call my-dir)

# the library
# ============================================================
include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
            $(call all-subdir-java-files)
            
LOCAL_MODULE := android.policy_phone
LOCAL_UNINSTALLABLE_MODULE := true

#include $(BUILD_JAVA_LIBRARY)
+341 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 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.internal.policy.impl;

import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OperationCanceledException;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.AccountManagerCallback;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.telephony.TelephonyManager;
import android.text.Editable;
import android.text.InputFilter;
import android.text.LoginFilter;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;

import java.io.IOException;

/**
 * When the user forgets their password a bunch of times, we fall back on their
 * account's login/password to unlock the phone (and reset their lock pattern).
 */
public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen,
        KeyguardUpdateMonitor.InfoCallback,View.OnClickListener, TextWatcher {
    private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
    private static final String LOCK_PATTERN_CLASS =
            "com.android.settings.ChooseLockPattern";

    /**
     * The amount of millis to stay awake once this screen detects activity
     */
    private static final int AWAKE_POKE_MILLIS = 30000;

    private final KeyguardScreenCallback mCallback;
    private final LockPatternUtils mLockPatternUtils;

    private TextView mTopHeader;
    private TextView mInstructions;
    private EditText mLogin;
    private EditText mPassword;
    private Button mOk;
    private Button mEmergencyCall;

    /**
     * Shown while making asynchronous check of password.
     */
    private ProgressDialog mCheckingDialog;

    /**
     * AccountUnlockScreen constructor.
     * @param configuration
     */
    public AccountUnlockScreen(Context context,Configuration configuration,
            KeyguardScreenCallback callback, LockPatternUtils lockPatternUtils) {
        super(context);
        mCallback = callback;
        mLockPatternUtils = lockPatternUtils;

        LayoutInflater.from(context).inflate(
                R.layout.keyguard_screen_glogin_unlock, this, true);

        mTopHeader = (TextView) findViewById(R.id.topHeader);
        mTopHeader.setText(mLockPatternUtils.isPermanentlyLocked() ?
                R.string.lockscreen_glogin_too_many_attempts :
                R.string.lockscreen_glogin_forgot_pattern);

        mInstructions = (TextView) findViewById(R.id.instructions);

        mLogin = (EditText) findViewById(R.id.login);
        mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } );
        mLogin.addTextChangedListener(this);

        mPassword = (EditText) findViewById(R.id.password);
        mPassword.addTextChangedListener(this);

        mOk = (Button) findViewById(R.id.ok);
        mOk.setOnClickListener(this);

        mEmergencyCall = (Button) findViewById(R.id.emergencyCall);
        mEmergencyCall.setOnClickListener(this);
        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
    }

    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before, int count) {
        mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
    }

    @Override
    protected boolean onRequestFocusInDescendants(int direction,
            Rect previouslyFocusedRect) {
        // send focus to the login field
        return mLogin.requestFocus(direction, previouslyFocusedRect);
    }

    /** {@inheritDoc} */
    public boolean needsInput() {
        return true;
    }

    /** {@inheritDoc} */
    public void onPause() {

    }

    /** {@inheritDoc} */
    public void onResume() {
        // start fresh
        mLogin.setText("");
        mPassword.setText("");
        mLogin.requestFocus();
        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
    }

    /** {@inheritDoc} */
    public void cleanUp() {
        if (mCheckingDialog != null) {
            mCheckingDialog.hide();
        }
    }

    /** {@inheritDoc} */
    public void onClick(View v) {
        mCallback.pokeWakelock();
        if (v == mOk) {
            asyncCheckPassword();
        }

        if (v == mEmergencyCall) {
            mCallback.takeEmergencyCallAction();
        }
    }

    private void onCheckPasswordResult(boolean success) {
        if (success) {
            // clear out forgotten password
            mLockPatternUtils.setPermanentlyLocked(false);
            mLockPatternUtils.setLockPatternEnabled(false);
            mLockPatternUtils.saveLockPattern(null);

            // launch the 'choose lock pattern' activity so
            // the user can pick a new one if they want to
            Intent intent = new Intent();
            intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            mContext.startActivity(intent);
            mCallback.reportSuccessfulUnlockAttempt();

            // close the keyguard
            mCallback.keyguardDone(true);
        } else {
            mInstructions.setText(R.string.lockscreen_glogin_invalid_input);
            mPassword.setText("");
            mCallback.reportFailedUnlockAttempt();
        }
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN
                && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            if (mLockPatternUtils.isPermanentlyLocked()) {
                mCallback.goToLockScreen();
            } else {
                mCallback.forgotPattern(false);
            }
            return true;
        }
        return super.dispatchKeyEvent(event);
    }

    /**
     * Given the string the user entered in the 'username' field, find
     * the stored account that they probably intended.  Prefer, in order:
     *
     *   - an exact match for what was typed, or
     *   - a case-insensitive match for what was typed, or
     *   - if they didn't include a domain, an exact match of the username, or
     *   - if they didn't include a domain, a case-insensitive
     *     match of the username.
     *
     * If there is a tie for the best match, choose neither --
     * the user needs to be more specific.
     *
     * @return an account name from the database, or null if we can't
     * find a single best match.
     */
    private Account findIntendedAccount(String username) {
        Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google");

        // Try to figure out which account they meant if they
        // typed only the username (and not the domain), or got
        // the case wrong.

        Account bestAccount = null;
        int bestScore = 0;
        for (Account a: accounts) {
            int score = 0;
            if (username.equals(a.name)) {
                score = 4;
            } else if (username.equalsIgnoreCase(a.name)) {
                score = 3;
            } else if (username.indexOf('@') < 0) {
                int i = a.name.indexOf('@');
                if (i >= 0) {
                    String aUsername = a.name.substring(0, i);
                    if (username.equals(aUsername)) {
                        score = 2;
                    } else if (username.equalsIgnoreCase(aUsername)) {
                        score = 1;
                    }
                }
            }
            if (score > bestScore) {
                bestAccount = a;
                bestScore = score;
            } else if (score == bestScore) {
                bestAccount = null;
            }
        }
        return bestAccount;
    }

    private void asyncCheckPassword() {
        mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
        final String login = mLogin.getText().toString();
        final String password = mPassword.getText().toString();
        Account account = findIntendedAccount(login);
        if (account == null) {
            onCheckPasswordResult(false);
            return;
        }
        getProgressDialog().show();
        Bundle options = new Bundle();
        options.putString(AccountManager.KEY_PASSWORD, password);
        AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
                new AccountManagerCallback<Bundle>() {
            public void run(AccountManagerFuture<Bundle> future) {
                try {
                    mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
                    final Bundle result = future.getResult();
                    final boolean verified = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
                    // ensure on UI thread
                    mLogin.post(new Runnable() {
                        public void run() {
                            onCheckPasswordResult(verified);
                        }
                    });
                } catch (OperationCanceledException e) {
                    onCheckPasswordResult(false);
                } catch (IOException e) {
                    onCheckPasswordResult(false);
                } catch (AuthenticatorException e) {
                    onCheckPasswordResult(false);
                } finally {
                    mLogin.post(new Runnable() {
                        public void run() {
                            getProgressDialog().hide();
                        }
                    });
                }
            }
        }, null /* handler */);
    }

    private Dialog getProgressDialog() {
        if (mCheckingDialog == null) {
            mCheckingDialog = new ProgressDialog(mContext);
            mCheckingDialog.setMessage(
                    mContext.getString(R.string.lockscreen_glogin_checking_password));
            mCheckingDialog.setIndeterminate(true);
            mCheckingDialog.setCancelable(false);
            mCheckingDialog.getWindow().setType(
                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
            if (!mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_sf_slowBlur)) {
                mCheckingDialog.getWindow().setFlags(
                        WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
                        WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
            }
        }
        return mCheckingDialog;
    }

    public void onPhoneStateChanged(String newState) {
        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
    }

    public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {

    }

    public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {

    }

    public void onRingerModeChanged(int state) {

    }

    public void onTimeChanged() {

    }
}
+578 −0

File added.

Preview size limit exceeded, changes collapsed.

+192 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 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.internal.policy.impl;

import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.TableMaskFilter;
import android.graphics.Typeface;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.DisplayMetrics;
import android.util.Log;
import android.content.res.Resources;
import android.content.Context;

/**
 * Various utilities shared amongst the Launcher's classes.
 */
final class IconUtilities {
    private static final String TAG = "IconUtilities";

    private static final int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };

    private int mIconWidth = -1;
    private int mIconHeight = -1;
    private int mIconTextureWidth = -1;
    private int mIconTextureHeight = -1;

    private final Paint mPaint = new Paint();
    private final Paint mBlurPaint = new Paint();
    private final Paint mGlowColorPressedPaint = new Paint();
    private final Paint mGlowColorFocusedPaint = new Paint();
    private final Rect mOldBounds = new Rect();
    private final Canvas mCanvas = new Canvas();
    private final DisplayMetrics mDisplayMetrics;

    private int mColorIndex = 0;

    public IconUtilities(Context context) {
        final Resources resources = context.getResources();
        DisplayMetrics metrics = mDisplayMetrics = resources.getDisplayMetrics();
        final float density = metrics.density;
        final float blurPx = 5 * density;

        mIconWidth = mIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size);
        mIconTextureWidth = mIconTextureHeight = mIconWidth + (int)(blurPx*2);

        mBlurPaint.setMaskFilter(new BlurMaskFilter(blurPx, BlurMaskFilter.Blur.NORMAL));
        mGlowColorPressedPaint.setColor(0xffffc300);
        mGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
        mGlowColorFocusedPaint.setColor(0xffff8e00);
        mGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));

        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0.2f);

        mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
                Paint.FILTER_BITMAP_FLAG));
    }

    public Drawable createIconDrawable(Drawable src) {
        Bitmap scaled = createIconBitmap(src);

        StateListDrawable result = new StateListDrawable();

        result.addState(new int[] { android.R.attr.state_focused },
                new BitmapDrawable(createSelectedBitmap(scaled, false)));
        result.addState(new int[] { android.R.attr.state_pressed },
                new BitmapDrawable(createSelectedBitmap(scaled, true)));
        result.addState(new int[0], new BitmapDrawable(scaled));

        result.setBounds(0, 0, mIconTextureWidth, mIconTextureHeight);
        return result;
    }

    /**
     * Returns a bitmap suitable for the all apps view.  The bitmap will be a power
     * of two sized ARGB_8888 bitmap that can be used as a gl texture.
     */
    private Bitmap createIconBitmap(Drawable icon) {
        int width = mIconWidth;
        int height = mIconHeight;

        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(mDisplayMetrics);
            }
        }
        int sourceWidth = icon.getIntrinsicWidth();
        int sourceHeight = icon.getIntrinsicHeight();

        if (sourceWidth > 0 && sourceWidth > 0) {
            // There are intrinsic sizes.
            if (width < sourceWidth || height < sourceHeight) {
                // It's too big, scale it down.
                final float ratio = (float) sourceWidth / sourceHeight;
                if (sourceWidth > sourceHeight) {
                    height = (int) (width / ratio);
                } else if (sourceHeight > sourceWidth) {
                    width = (int) (height * ratio);
                }
            } else if (sourceWidth < width && sourceHeight < height) {
                // It's small, use the size they gave us.
                width = sourceWidth;
                height = sourceHeight;
            }
        }

        // no intrinsic size --> use default size
        int textureWidth = mIconTextureWidth;
        int textureHeight = mIconTextureHeight;

        final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
                Bitmap.Config.ARGB_8888);
        final Canvas canvas = mCanvas;
        canvas.setBitmap(bitmap);

        final int left = (textureWidth-width) / 2;
        final int top = (textureHeight-height) / 2;

        if (false) {
            // draw a big box for the icon for debugging
            canvas.drawColor(sColors[mColorIndex]);
            if (++mColorIndex >= sColors.length) mColorIndex = 0;
            Paint debugPaint = new Paint();
            debugPaint.setColor(0xffcccc00);
            canvas.drawRect(left, top, left+width, top+height, debugPaint);
        }

        mOldBounds.set(icon.getBounds());
        icon.setBounds(left, top, left+width, top+height);
        icon.draw(canvas);
        icon.setBounds(mOldBounds);

        return bitmap;
    }

    private Bitmap createSelectedBitmap(Bitmap src, boolean pressed) {
        final Bitmap result = Bitmap.createBitmap(mIconTextureWidth, mIconTextureHeight,
                Bitmap.Config.ARGB_8888);
        final Canvas dest = new Canvas(result);

        dest.drawColor(0, PorterDuff.Mode.CLEAR);

        int[] xy = new int[2];
        Bitmap mask = src.extractAlpha(mBlurPaint, xy);

        dest.drawBitmap(mask, xy[0], xy[1],
                pressed ? mGlowColorPressedPaint : mGlowColorFocusedPaint);

        mask.recycle();

        dest.drawBitmap(src, 0, 0, mPaint);

        return result;
    }
}
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 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.internal.policy.impl;

/**
 * Common interface of each {@link android.view.View} that is a screen of
 * {@link LockPatternKeyguardView}.
 */
public interface KeyguardScreen {

    /**
     * Return true if your view needs input, so should allow the soft
     * keyboard to be displayed.
     */
    boolean needsInput();
    
    /**
     * This screen is no longer in front of the user.
     */
    void onPause();

    /**
     * This screen is going to be in front of the user.
     */
    void onResume();

    /**
     * This view is going away; a hook to do cleanup.
     */
    void cleanUp();
}
Loading