package com.github.jinsen47.pokefaker;

import android.content.ContentResolver;
import android.location.Location;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

/**
 * Created by Jinsen on 16/7/16.
 * Mock by add mock providers
 */
public class MockProviderFaker implements IXposedHookLoadPackage {

    private static final Set<String> mPackageSet = new HashSet<String>() {{
       add("com.nianticlabs.pokemongo");
    }};
    private static final String TAG = MockProviderFaker.class.getSimpleName();

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        preventGetMockLocationSetting(lpparam);
        preventCheckFromMockProvider(lpparam);
//        dumpLocation(lpparam);
    }

    private void dumpLocation(XC_LoadPackage.LoadPackageParam lpparam) {
        if (lpparam.packageName.equals("com.nianticlabs.pokemongo")) {
            XposedHelpers.findAndHookMethod(
                    "com.nianticlabs.nia.location.NianticLocationManager", /* class name*/
                    lpparam.classLoader,
                    "locationUpdate", /* method name */
                    Location.class, /* params list */
                    int[].class,
                    new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    Location location = ((Location) param.args[0]);
                    int[] status = ((int[]) param.args[1]);
                    if (location != null) {
                        XposedBridge.log(location.toString());
                        if (location.getExtras() != null) {
                            XposedBridge.log(location.getExtras().toString());
                        }
                    } else {
                        XposedBridge.log("location == null");
                    }
                    XposedBridge.log("status = " + Arrays.toString(status));
                }
            });
        }
    }

    private void preventGetMockLocationSetting(XC_LoadPackage.LoadPackageParam lpparam) {
        if (!mPackageSet.contains(lpparam.packageName)) return;
        // hook Settings.Secure.getInt(ContentResolver, String)
        XposedHelpers.findAndHookMethod(
                Settings.Secure.class,
                "getInt",
                ContentResolver.class,
                String.class,
                new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        String name = ((String) param.args[1]);
                        if (name.equals(Settings.Secure.ALLOW_MOCK_LOCATION)) {
                            Log.d(TAG, "Bingo, find its calling");
                            param.setResult(0);
                        }
                    }
                });
        // hook Settings.Secure.getString(ContentResolver, String)
        XposedHelpers.findAndHookMethod(
                Settings.Secure.class,
                "getString",
                ContentResolver.class,
                String.class,
                new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        String name = ((String) param.args[1]);
                        if (name.equals(Settings.Secure.ALLOW_MOCK_LOCATION)) {
                            Log.d(TAG, "Bingo, find its calling");
                            param.setResult("0");
                        }
                    }
                });
    }

    private void preventCheckFromMockProvider(final XC_LoadPackage.LoadPackageParam lpparam) {
        if (Build.VERSION.SDK_INT >= 18 && mPackageSet.contains(lpparam.packageName)) {
            // hook Location.isFromMockProvider()
            XposedHelpers.findAndHookMethod(
                    Location.class,
                    "isFromMockProvider",
                    new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            XposedHelpers.setBooleanField(param.thisObject, "mIsFromMockProvider", false);
                            Log.d(TAG, param.thisObject.getClass().getName() + "is calling from mock provider");
                            param.setResult(false);
                        }
            });
        }
    }
}

@@ -3118,36 +3118,43 @@
 find its calling
+ getInt
 %22);%0A
-
                 
@@ -3869,16 +3869,26 @@
  calling
+ getString
 %22);%0A    
@@ -3997,24 +3997,942 @@
         %7D);%0A
+        // hook Settings.Secure.getStringForUser(ContentResolver, String, int)%0A        if (Build.VERSION.SDK_INT %3E= 17) %7B%0A            XposedHelpers.findAndHookMethod(%0A                    Settings.Secure.class,%0A                    %22getStringForUser%22,%0A                    ContentResolver.class,%0A                    String.class,%0A                    int.class,%0A                    new XC_MethodHook() %7B%0A                        @Override%0A                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable %7B%0A                            String name = ((String) param.args%5B1%5D);%0A                            if (name.equals(Settings.Secure.ALLOW_MOCK_LOCATION)) %7B%0A                                Log.d(TAG, %22Bingo, find its calling getStringForUser%22);%0A                                param.setResult(%220%22);%0A                            %7D%0A                        %7D%0A                    %7D);%0A        %7D%0A
     %7D%0A%0A    p
@@ -5013,32 +5013,32 @@
 aram lpparam) %7B%0A
+
         if (Buil
@@ -5064,53 +5064,8 @@
 = 18
- && mPackageSet.contains(lpparam.packageName)
 ) %7B%0A

Fix a xposed module bug on Android M