Repo Created

This commit is contained in:
Fr4nz D13trich 2025-11-15 17:44:12 +01:00
parent eb305e2886
commit a8c22c65db
4784 changed files with 329907 additions and 2 deletions

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ SPDX-FileCopyrightText: 2023 microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application>
<receiver
android:name="com.huawei.signature.diff.InitReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<provider
android:name="com.huawei.signature.diff.InitProvider"
android:authorities="${applicationId}.signature.diff.init"
android:enabled="true"
android:exported="false"
android:initOrder="1000" />
<service
android:name="com.huawei.signature.diff.SignatureService"
android:process=":signature"
android:exported="true">
<intent-filter>
<action android:name="com.huawei.signature.diff" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
</manifest>

View file

@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.huawei.signature.diff;
/**
* Interface for Huawei Differentiated Signature Capability
* See https://forums.developer.huawei.com/forumPortal/en/topic/0202128603315033024
*/
interface ISignatureService {
String[] querySignature(String packageName, boolean suggested);
}

View file

@ -0,0 +1,75 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.huawei.signature.diff;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import org.microg.signature.fake.R;
public class AppListDatabaseOpenHelper extends SQLiteOpenHelper {
private static final String TAG = AppListDatabaseOpenHelper.class.getSimpleName();
private static final String DATABASE_NAME = "app_list.db";
public static final String TABLE_APPLIST = "applist";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_FAKE = "fake";
private static final int DATABASE_VERSION = 3;
private static final String DROP_APP_LIST_TABLE = "DROP TABLE IF EXISTS " + TABLE_APPLIST;
private static final String CREATE_APP_LIST_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_APPLIST + "(" +
COLUMN_NAME + " VARCHAR(255) PRIMARY KEY, " +
COLUMN_FAKE + " INTEGER CHECK(" + COLUMN_FAKE + " >= 0 and " + COLUMN_FAKE + " <= 1)" +
")";
private final Context context;
public AppListDatabaseOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG, "onCreate");
db.execSQL(DROP_APP_LIST_TABLE);
db.execSQL(CREATE_APP_LIST_TABLE);
initData(db);
}
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
if (!db.isReadOnly()) {
initData(db);
}
}
private void initData(SQLiteDatabase db) {
String[] wantFakeApps = context.getResources().getStringArray(R.array.signature_want_fake);
String[] neverFakeApps = context.getResources().getStringArray(R.array.signature_never_fake);
if (wantFakeApps.length == 0 && neverFakeApps.length == 0) {
return;
}
for (String app : wantFakeApps) {
db.insertWithOnConflict(TABLE_APPLIST, null, generateValues(app, true), SQLiteDatabase.CONFLICT_REPLACE);
}
for (String app : neverFakeApps) {
db.insertWithOnConflict(TABLE_APPLIST, null, generateValues(app, false), SQLiteDatabase.CONFLICT_REPLACE);
}
}
private ContentValues generateValues(String packageName, boolean fake) {
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMN_NAME, packageName);
contentValues.put(COLUMN_FAKE, fake ? 1 : 0);
return contentValues;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onCreate(db);
}
}

View file

@ -0,0 +1,72 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.huawei.signature.diff;
import android.app.ActivityManager;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import java.util.List;
public class InitProvider extends ContentProvider {
private static final String TAG = "InitProvider";
@Override
public boolean onCreate() {
Log.d(TAG, "onCreate");
if (!isServiceRunning(getContext(), getContext().getPackageName(), SignatureService.class.getName())) {
Intent intent = new Intent(getContext(), SignatureService.class);
try {
getContext().startService(intent);
} catch (Exception ignored) {
}
}
return false;
}
private boolean isServiceRunning(Context context, String packageName, String serviceName) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceInfoList = manager.getRunningServices(Integer.MAX_VALUE);
if (serviceInfoList == null) {
return false;
}
for (ActivityManager.RunningServiceInfo info : serviceInfoList) {
if (info.service.getPackageName().equals(packageName) && info.service.getClassName().equals(serviceName)) {
return true;
}
}
return false;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}

View file

@ -0,0 +1,29 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.huawei.signature.diff;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* This is to make sure the process is initialized at boot.
*/
public class InitReceiver extends BroadcastReceiver {
private static final String TAG = "InitReceiver";
@SuppressLint("UnsafeProtectedBroadcastReceiver")
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive");
try {
context.startService(new Intent(context, SignatureService.class));
} catch (Exception ignored) {
}
}
}

View file

@ -0,0 +1,106 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.huawei.signature.diff;
import static com.huawei.signature.diff.AppListDatabaseOpenHelper.COLUMN_NAME;
import static com.huawei.signature.diff.AppListDatabaseOpenHelper.TABLE_APPLIST;
import android.app.Service;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import org.microg.signature.fake.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Date;
public class SignatureService extends Service {
private static final String TAG = "SignatureService";
private SQLiteDatabase database;
private AppListDatabaseOpenHelper openHelper;
private long start;
@Override
public void onCreate() {
super.onCreate();
this.openHelper = new AppListDatabaseOpenHelper(this);
this.database = openHelper.getWritableDatabase();
this.start = System.currentTimeMillis();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onDestroy() {
this.openHelper.close();
super.onDestroy();
}
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
writer.println("Started: " + new Date(start));
}
private final ISignatureService.Stub binder = new ISignatureService.Stub() {
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
if (Binder.getCallingUid() > 10000) {
Log.w(TAG, "Illegal access from app");
reply.writeException(new UnsupportedOperationException("Illegal"));
return true;
}
return super.onTransact(code, data, reply, flags);
}
@Override
public String[] querySignature(String packageName, boolean suggested) throws RemoteException {
try (Cursor cursor = database.query(TABLE_APPLIST, null, COLUMN_NAME + "=?",
new String[]{packageName}, null, null, null)) {
switch (cursor.getCount()) {
case 0:
return getResult(suggested);
case 1:
if (cursor.moveToFirst()) {
int shouldFake = cursor.getInt(1);
return getResult(shouldFake == 1);
}
break;
default:
throw new IllegalArgumentException("result size: " + cursor.getCount());
}
} catch (Exception e) {
Log.w(TAG, e);
}
return getResult(false);
}
private String[] getResult(boolean useFakeSignature) {
if (useFakeSignature) {
return new String[]{getString(R.string.fake_signature),};
} else {
return new String[]{getString(R.string.real_signature),};
}
}
};
}