package com.android.facelock; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.os.Parcel; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.RelativeLayout; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; public class XposedHelper implements IXposedHookLoadPackage { public void handleLoadPackage( final LoadPackageParam lpparam ) throws Throwable { try { if ( !lpparam.packageName.equals( "com.android.keyguard" ) && !lpparam.packageName.equals( "com.android.facelock" ) && !lpparam.packageName.equals( "com.android.settings" ) ) return; if ( lpparam.packageName.equals( "com.android.settings" ) ) { // Allow password as a fallback findAndHookMethod( "com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment", lpparam.classLoader, "allowedForFallback", String.class, new XC_MethodHook() { @Override protected void afterHookedMethod( MethodHookParam param ) throws Throwable { if ( ( ( String ) param.args[ 0 ] ).equals( "unlock_set_password" ) ) param.setResult( true ); } } ); return; } if ( lpparam.packageName.equals( "com.android.facelock" ) ) { findAndHookMethod( "com.android.facelock.FaceLockService", lpparam.classLoader, "shouldFadeIn", new XC_MethodReplacement() { @Override protected Object replaceHookedMethod( MethodHookParam param ) throws Throwable { return true; } } ); return; } // Disable cancel button and change bg image 1/2 findAndHookMethod( "com.android.keyguard.FaceUnlock", lpparam.classLoader, "initializeView", View.class, new XC_MethodHook() { @Override protected void afterHookedMethod( MethodHookParam param ) throws Throwable { View v = ( View ) param.args[ 0 ]; Resources res = v.getResources(); ImageButton cancel = ( ImageButton ) v.findViewById( res.getIdentifier( "face_unlock_cancel_button", "id", "com.android.keyguard" ) ); cancel.setVisibility( View.GONE ); // Change bg image XposedHelpers.callMethod( param.thisObject, "start" ); } } ); // Fix padlock button being impossible to press (??) findAndHookMethod( "com.android.keyguard.SlidingChallengeLayout", lpparam.classLoader, "onMeasure", int.class, int.class, new XC_MethodHook() { @Override protected void afterHookedMethod( MethodHookParam param ) throws Throwable { XposedHelpers.callMethod( param.thisObject, "setChallengeInteractive", true ); } } ); // Change background image to user's image 2/2 findAndHookMethod( "com.android.keyguard.FaceUnlock", lpparam.classLoader, "handleServiceConnected", new XC_MethodHook() { @Override protected void afterHookedMethod( MethodHookParam param ) throws Throwable { View v = ( View ) XposedHelpers.getObjectField( param.thisObject, "mFaceUnlockView" ); View spotlightMask = v.findViewById( v.getResources().getIdentifier( "spotlightMask", "id", "com.android.keyguard" ) ); // This ensures we only run the code once! if ( spotlightMask.getVisibility() == View.GONE ) return; spotlightMask.setVisibility( View.GONE ); Object binderProxy = XposedHelpers.getObjectField( XposedHelpers.getObjectField( param.thisObject, "mService" ), "mRemote" ); Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); XposedHelpers.callMethod( binderProxy, "transact", 0x4747, data, reply, 0 ); Bitmap img = ( Bitmap ) reply.readValue( null ); // Create an ImageView so it doesn't stretch the image... ImageView imageView = new ImageView( v.getContext() ); imageView.setScaleType( ScaleType.CENTER_CROP ); imageView.setImageDrawable( new BitmapDrawable( v.getResources(), img ) ); imageView.setLayoutParams( new RelativeLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) ); imageView.setVisibility( View.VISIBLE ); // And add it to the layout ( ( RelativeLayout ) v ).addView( imageView, 0, imageView.getLayoutParams() ); data.recycle(); reply.recycle(); } } ); } catch ( Throwable e ) { XposedBridge.log( e ); } } }