Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
-keep class rikka.shizuku.** { *; }
-keep class dev.rikka.shizuku.** { *; }

# Shevery rules
-keep class com.hamondev.shevery.** { *; }

# Kotlin Reflect
-keep class kotlin.reflect.** { *; }
-keep class com.sameerasw.essentials.domain.model.** { *; }
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<uses-permission
android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="com.hamondev.shevery.permission.PRIVILEGED_API" />
<uses-permission android:name="moe.shizuku.manager.permission.API_V23" />
<uses-permission android:name="moe.shizuku.privileged.api.permission.BIND_SHIZUKU_SERVICE" />
<uses-permission
Expand Down Expand Up @@ -106,6 +107,7 @@
<queries>
<package android:name="com.sameerasw.overcast" />
<package android:name="eu.darken.porter" />
<package android:name="com.hamondev.shevery" />
<package android:name="com.google.android.apps.wear.companion" />
<intent>
<action android:name="com.sameerasw.island.PROVIDER" />
Expand Down Expand Up @@ -753,6 +755,14 @@
android:multiprocess="false"
android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" />

<provider
android:name="com.hamondev.shevery.api.SheveryProvider"
android:authorities="${applicationId}.shevery"
android:enabled="true"
android:exported="true"
android:multiprocess="false"
android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" />

<receiver
android:name="moe.shizuku.api.SystemServiceHelper$Receiver"
android:exported="true" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.hamondev.shevery.api;

import androidx.annotation.RestrictTo;

import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;

/**
* Constants for the native Shevery Privilege API and the Shizuku Stub compatibility layer.
* <p>
* Native Shevery clients use {@link #PERMISSION_PRIVILEGED_API} and {@link #PROVIDER_SUFFIX},
* while legacy {@code moe.shizuku.manager.permission.API_V23} requests are isolated in the
* Shizuku Stub ({@link #SHIZUKU_STUB_APPLICATION_ID}).
*/
public final class SheveryApiConstants {

private SheveryApiConstants() {
}

public static final int SERVER_VERSION = 14;
public static final int SERVER_PATCH_VERSION = 5;

// Binder interface
public static final String BINDER_DESCRIPTOR = "moe.shizuku.server.IShizukuService";
public static final int BINDER_TRANSACTION_transact = 1;

// Package identifiers
public static final String MANAGER_APPLICATION_ID = "com.hamondev.shevery";
public static final String SHIZUKU_STUB_APPLICATION_ID = "moe.shizuku.privileged.api";

// Native Shevery permissions (owned by com.hamondev.shevery)
public static final String PERMISSION_GROUP_API = "com.hamondev.shevery.permission-group.API";
public static final String PERMISSION_PRIVILEGED_API = "com.hamondev.shevery.permission.PRIVILEGED_API";
public static final String PERMISSION_MANAGER = "com.hamondev.shevery.permission.MANAGER";

// Legacy Shizuku permissions (offloaded to Shizuku Stub moe.shizuku.privileged.api)
public static final String LEGACY_SHIZUKU_PERMISSION = "moe.shizuku.manager.permission.API_V23";
public static final String LEGACY_SHIZUKU_PERMISSION_V22 = "moe.shizuku.manager.permission.API";
public static final String LEGACY_SHIZUKU_MANAGER_PERMISSION = "moe.shizuku.manager.permission.MANAGER";

// Client metadata markers
public static final String META_DATA_CLIENT_SUPPORT = "com.hamondev.shevery.client.PRIVILEGED_API_SUPPORT";
public static final String LEGACY_META_DATA_CLIENT_SUPPORT = "moe.shizuku.client.V3_SUPPORT";

// ContentProvider authorities & methods
public static final String PROVIDER_SUFFIX = ".shevery";
public static final String LEGACY_PROVIDER_SUFFIX = ".shizuku";
public static final String MANAGER_PROVIDER_AUTHORITY = MANAGER_APPLICATION_ID + PROVIDER_SUFFIX;
public static final String MANAGER_LEGACY_PROVIDER_AUTHORITY = MANAGER_APPLICATION_ID + LEGACY_PROVIDER_SUFFIX;
public static final String MANAGER_CONNECTOR_AUTHORITY = MANAGER_APPLICATION_ID + ".connector";

public static final String METHOD_SEND_BINDER = "sendBinder";
public static final String METHOD_GET_BINDER = "getBinder";
public static final String METHOD_REQUEST_BINDER = "requestBinder";
public static final String METHOD_SEND_USER_SERVICE = "sendUserService";

// Extras & broadcast actions
public static final String EXTRA_BINDER = "com.hamondev.shevery.intent.extra.BINDER";
public static final String LEGACY_EXTRA_BINDER = "moe.shizuku.privileged.api.intent.extra.BINDER";
public static final String EXTRA_PERMISSION_CHANNEL = "com.hamondev.shevery.intent.extra.PERMISSION_CHANNEL";
public static final String EXTRA_REQUESTED_PERMISSION = "com.hamondev.shevery.intent.extra.REQUESTED_PERMISSION";

public static final String ACTION_BINDER_RECEIVED = "com.hamondev.shevery.api.action.BINDER_RECEIVED";
public static final String ACTION_REQUEST_PERMISSION = "com.hamondev.shevery.intent.action.REQUEST_PERMISSION";
public static final String ACTION_REQUEST_BINDER = "com.hamondev.shevery.intent.action.REQUEST_BINDER";

// Attach application channel negotiation
public static final String ATTACH_APPLICATION_CLIENT_CHANNEL = "shevery:attach-client-channel";
public static final String CHANNEL_SHEVERY_NATIVE = "shevery_native";
public static final String CHANNEL_SHIZUKU_STUB = "shizuku_stub";

@RestrictTo(LIBRARY_GROUP_PREFIX)
public static final String USER_SERVICE_ARG_TOKEN = "shizuku:user-service-arg-token";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.hamondev.shevery.api;

import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.FileDescriptor;
import java.util.Objects;

/**
* Direct, zero-legacy-branch {@link IBinder} wrapper for the Shevery Privilege API.
* <p>
* Routes system service binder transactions directly through
* {@link SheveryPrivilege#transactRemote(Parcel, Parcel, int)} without legacy pre-v13 checks.
*/
public final class SheveryBinderWrapper implements IBinder {

private final IBinder original;

public SheveryBinderWrapper(@NonNull IBinder original) {
this.original = Objects.requireNonNull(original, "original binder must not be null");
}

@NonNull
public IBinder getOriginal() {
return original;
}

@Override
public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
Parcel newData = Parcel.obtain();
try {
newData.writeInterfaceToken(SheveryApiConstants.BINDER_DESCRIPTOR);
newData.writeStrongBinder(original);
newData.writeInt(code);
newData.writeInt(flags);
newData.appendFrom(data, 0, data.dataSize());
SheveryPrivilege.transactRemote(newData, reply, 0);
} finally {
newData.recycle();
}
return true;
}

@Nullable
@Override
public String getInterfaceDescriptor() throws RemoteException {
return original.getInterfaceDescriptor();
}

@Override
public boolean pingBinder() {
return original.pingBinder();
}

@Override
public boolean isBinderAlive() {
return original.isBinderAlive();
}

@Nullable
@Override
public IInterface queryLocalInterface(@NonNull String descriptor) {
return null;
}

@Override
public void dump(@NonNull FileDescriptor fd, @Nullable String[] args) throws RemoteException {
original.dump(fd, args);
}

@Override
public void dumpAsync(@NonNull FileDescriptor fd, @Nullable String[] args) throws RemoteException {
original.dumpAsync(fd, args);
}

@Override
public void linkToDeath(@NonNull DeathRecipient recipient, int flags) throws RemoteException {
original.linkToDeath(recipient, flags);
}

@Override
public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags) {
return original.unlinkToDeath(recipient, flags);
}
}
Loading
Loading