Android R版本 MtkSettings和Telephony进程通信aidl

需要获取simunlockstate状态,而这个不由我们这边控制,在免于提Mtk case的情况下,通过Telephony获取这个值,telephony是个服务apk,不能通过android.bp引入,考虑到这个原因,我觉得通过aidl以telephony为服务器端,MtkSettings为客户端,进行跨进程通信。下面说下步骤:
1.在服务器端新建aidl目录和文件,这里通过AndroidStudio去生成(New -> Aidl ->AIDL File)。生成完后记得rebuild一下,但是我这个是源码工程,rebuild后肯定会报错,但只要生成aidl生成了相应的派生类那就没关系。

// INetworkUnlockStatus.aidl
package com.android;

// Declare any non-default types here with import statements

interface INetworkUnlockStatus {
    int getNetworkUnlockStatus();
}

2.服务器端建立service

public class NetworkUnlockService extends Service {

    private final String TAG = "NetworkUnlockService";

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "getNetworkUnlockStatus has onBind");
        return mUnlockManager;
    }

    private final INetworkUnlockStatus.Stub mUnlockManager = new INetworkUnlockStatus.Stub() {
        @Override
        public int getNetworkUnlockStatus() throws RemoteException {
            Log.d(TAG, "getNetworkUnlockStatus has exec");
            return getState();
        }
    };

    int getState() {
        MtkPhoneInterfaceManagerEx mtkPhoneInterfaceManagerEx = MtkPhoneInterfaceManagerEx.init((PhoneGlobals) getApplicationContext());
        int simLockStateForRSU = mtkPhoneInterfaceManagerEx.getSimLockStateForRSU(0);
        return simLockStateForRSU;
    }

}

记得声明下并且export为true:

        <service android:name=".NetworkUnlockService"
            android:exported="true"
            android:enabled="true">
            <intent-filter
                >
                <action android:name="com.unlock.state.aidl"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>

3.移植aidl包到客户端主目录,和main同级即可,确保包名一致
4.客户端合适的时机去启动远程service:

        Intent intent = new Intent();
        intent.setAction("com.unlock.state.aidl");
        intent.setPackage("com.android.phone");
        mContext.bindServiceAsUser(intent, mCon, Context.BIND_AUTO_CREATE, UserHandle.CURRENT);

ServiceConnection:

    private ServiceConnection mCon = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected");
            INetworkUnlockStatus asInterface = INetworkUnlockStatus.Stub.asInterface(service);
            if (null != asInterface) {
                try {
                    networkUnlockStatus = asInterface.getNetworkUnlockStatus();
                    Log.d(TAG, "onServiceConnected networkUnlockStatus:" + networkUnlockStatus);
                } catch (RemoteException e) {
                    Log.d(TAG, "onServiceConnected RemoteException e:" + e.getMessage());
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected");
        }
    };

注意,如果用的是bindService会爆错误无法运行Calling a method in the system process without a qualified user,根据源码就知道需要调用bindServiceAsUser,其实bindService后面也是调用了bindServiceAsUser的。

5.由于我这是在源码层的修改,所以需要在Android.bp进行aidl包的导入,注意在android R之前可能是Android.mk。下面代码只要看
srcs: [“src/**/*.java”,“aidl/com/android/INetworkUnlockStatus.aidl”],
这个位置即可:

// Build the Settings APK
android_library {
    name: "MtkSettings-core",
    platform_apis: true,
    defaults: [
        "MtkSettingsLibDefaults",
        "SettingsLibDefaults",
        "SettingsLib-search-defaults",
    ],

    srcs: ["src/**/*.java","aidl/com/android/INetworkUnlockStatus.aidl"],

    resource_dirs: [
        "res",
        "res_ext",
    ],

    static_libs: [
        "nfc_settings_adapter",
        "androidx-constraintlayout_constraintlayout",
        "androidx.slice_slice-builders",
        "androidx.slice_slice-core",
        "androidx.slice_slice-view",
        "androidx.core_core",
        "androidx.appcompat_appcompat",
        "androidx.cardview_cardview",
        "androidx.preference_preference",
        "androidx.recyclerview_recyclerview",
        "com.google.android.material_material",
        "setupcompat",
        "setupdesign",
        "androidx-constraintlayout_constraintlayout-solver",
        "androidx.lifecycle_lifecycle-runtime",
        "androidx.lifecycle_lifecycle-extensions",
        "guava",
        "jsr305",
        "com.mediatek.lbs.em2.utils",
        "mtksettings-contextual-card-protos-lite",
        "mtksettings-log-bridge-protos-lite",
        "mtkcontextualcards",
        "mtksettings-logtags",
        "com.mediatek.settings.ext",
        "statslog-mtksettings",
        "zxing-core-1.7",
        "android.hardware.dumpstate-V1.0-java",
        "android.hardware.dumpstate-V1.1-java",
    ],

    libs: [
        "telephony-common",
        "ims-common",
        "app-compat-annotations",
        "mediatek-telephony-base",
        "mediatek-telephony-common",
        "mediatek-common",
        "mediatek-framework",
        "mediatek-ims-common",
    ],
}

Telephony的Android.bp也是一样,我就不重复了。
客户端调用完整代码:

public class NetworkUnlockPreferenceController extends BasePreferenceController implements PreferenceManager.OnActivityStopListener {

    private Context mContext;
    String packageName = "com.assurance.rsuapp";
    String className = "com.tmobile.rsuapp.MainActivity";
    private String TAG = "NetworkUnlockPreferenceController";
    private int networkUnlockStatus;

    public NetworkUnlockPreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
        mContext = context;
    }

    @Override
    public int getAvailabilityStatus() {
        return AVAILABLE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
    }

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
            return false;
        }
        ComponentName componentName = new ComponentName(packageName, className);
        startApp(componentName, null);
        return true;
    }

    @Override
    public CharSequence getSummary() {
        startUnlockStatusService();
        String state = "";
        switch (networkUnlockStatus) {
            case 0:
                state = mContext.getResources().getString(R.string.locked_status);
                break;
            case 1:
                state = mContext.getResources().getString(R.string.temporarily_locked_status);
                break;
            case 2:
                state = mContext.getResources().getString(R.string.permanently_locked_status);
                break;
        }
        return state;
    }

    @TargetApi(Build.VERSION_CODES.DONUT)
    private void startUnlockStatusService() {
        Intent intent = new Intent();
        intent.setAction("com.unlock.state.aidl");
        intent.setPackage("com.android.phone");
        mContext.bindServiceAsUser(intent, mCon, Context.BIND_AUTO_CREATE, UserHandle.CURRENT);
    }

    private ServiceConnection mCon = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected");
            INetworkUnlockStatus asInterface = INetworkUnlockStatus.Stub.asInterface(service);
            if (null != asInterface) {
                try {
                    networkUnlockStatus = asInterface.getNetworkUnlockStatus();
                    Log.d(TAG, "onServiceConnected networkUnlockStatus:" + networkUnlockStatus);
                } catch (RemoteException e) {
                    Log.d(TAG, "onServiceConnected RemoteException e:" + e.getMessage());
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected");
        }
    };


    private void startApp(ComponentName com, String param) {
        if (com != null) {
            PackageInfo packageInfo;
            try {
                packageInfo = mContext.getPackageManager().getPackageInfo(com.getPackageName(), 0);
            } catch (PackageManager.NameNotFoundException e) {
                packageInfo = null;
                e.printStackTrace();
            }
            try {
                Intent intent = new Intent();
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.setComponent(com);
                if (param != null) {
                    Bundle bundle = new Bundle();
                    bundle.putString("flag", param);
                    intent.putExtras(bundle);
                }
                mContext.startActivity(intent);
            } catch (Exception e) {
                Log.e(TAG, "Exception", e);
            }
        }
    }

    @Override
    public void onActivityStop() {
        mContext.unbindService(mCon);
    }
}

6.需要注意的是,我在preference里绑定的service,而preference类似activity,fragment的生命周期,所以我实现PreferenceManager.OnActivityStopListener,在对应的Activity销毁的时候进行解绑service。另外,Telephony编译生成的apk是不能直接adb install -r安装的,也不能直接push,需要先删除之前的telephony即可push,然后reboot就能生效,MtkSettings的话可以直接install -r,也不要重启。

猜你喜欢

转载自blog.csdn.net/kururunga/article/details/110421578
今日推荐