improve backup function

This commit is contained in:
Li 2024-04-29 00:52:34 +12:00
parent 50180c78e1
commit 75ee1d7b16
12 changed files with 246 additions and 46 deletions

View File

@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.READ_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

View File

@ -0,0 +1,77 @@
package com.psmreborn.nopsmdrm;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import java.io.File;
import java.io.IOException;
public class DumpAllRifs {
public static void setDumpAllFlagAndStartPsm(Activity ctx) {
ProgressDialog dialog = new ProgressDialog(ctx);
dialog.setTitle("Starting PSM ...");
dialog.setMessage("Please Wait ...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
new Thread(() -> {
Handler handler = new Handler(ctx.getMainLooper());
File psmFolder = new File(Environment.getExternalStorageDirectory(), "psm");
File psmDumpAllFlagFile = new File(psmFolder, "dump_all");
File psmAndroidFolder = new File(new File(new File(new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data"), "com.playstation.psstore"), "files"), "psm");
// stop psm
Helper.killPsm();
try {
psmDumpAllFlagFile.createNewFile();
} catch (IOException e) {
return;
}
// get a games title id..
String titleId = "";
String[] allGames = psmAndroidFolder.list();
for(String chkTitleId : allGames) {
File appInfoFile = new File(new File(new File(psmAndroidFolder, chkTitleId), "Application"), "app.info");
if(appInfoFile.exists()){
titleId = chkTitleId;
}
}
if(titleId.equals("")){
return;
}
Log.d("DUMPALLRIFS", "Using TitleID: "+titleId);
WifiManager wifiManager = (WifiManager) ctx.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if(wifiManager != null){
Intent intent = new Intent("com.playstation.psm.intent.action.START_CONTENT");
intent.putExtra("titleId", titleId);
intent.setData(Uri.parse("psgmpsm:play?titleId="+titleId));
handler.post(() -> {
// disable wifi
wifiManager.setWifiEnabled(false);
// start psm ...
ctx.startActivity(intent);
dialog.dismiss();
});
}
else{
return;
}
}).start();
}
}

View File

@ -1,5 +1,7 @@
package com.psmreborn.nopsmdrm;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
@ -40,6 +42,10 @@ public class Helper {
return true;
}
public static void killPsm(){
ActivityManager am = (ActivityManager) ctx.getSystemService(Activity.ACTIVITY_SERVICE);
am.killBackgroundProcesses("com.playstation.psstore");
}
public static ApplicationInfo getAppInfo(String pkg) throws PackageManager.NameNotFoundException {
ApplicationInfo appInfo = ctx.getPackageManager().getApplicationInfo(pkg, 0);
return appInfo;

View File

@ -3,8 +3,14 @@ package com.psmreborn.nopsmdrm;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@ -13,9 +19,12 @@ import android.view.View;
import com.psmreborn.nopsmdrm.pscertified.PlayStationCertified;
import com.psmreborn.nopsmdrm.pscertified.PsCertificatesInstaller;
import java.io.File;
public class MainActivity extends Activity {
/*
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
@ -37,6 +46,7 @@ public class MainActivity extends Activity {
return super.onOptionsItemSelected(item);
}
}
*/
@Override
public void onCreate(Bundle savedInstanceState) {
@ -54,23 +64,43 @@ public class MainActivity extends Activity {
super.onBackPressed();
}
private void psCertifiedAlert(){
new AlertDialog.Builder((Activity)this)
.setTitle("PS Certification Missing")
.setMessage("Your device appears to not be\"PlayStation Certified\"\nDo you want to certify it?\n(Warning: modifies /system/)")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
(new PsCertificatesInstaller(MainActivity.this)).execute();
}
})
.setNegativeButton("No", null).show();
}
public void installStart(View view) {
PlayStationCertified playStationCertified = new PlayStationCertified(this);
if(!playStationCertified.isPlaystationCertified()){
new AlertDialog.Builder((Activity)this)
.setTitle("PS Certification Missing")
.setMessage("Your device appears to not be\"PlayStation Certified\"\nDo you want to certify it?\n(Warning: modifies /system/)")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
(new PsCertificatesInstaller(MainActivity.this)).execute();
}
})
.setNegativeButton("No", null).show();
psCertifiedAlert();
}
else {
(new NoPsmDrmInstaller(this)).execute();
}
}
public void dumpAllRifs(View view){
String rifOutput = new File(Environment.getExternalStorageDirectory(), "psm").getAbsolutePath();
new AlertDialog.Builder((Activity)this)
.setTitle("Backup licenses")
.setMessage("This will show a black screen for awhile\nthen a PlayStation Mobile game will start\nOnce the game starts, a backup of all your PSM licenses can be found at\n\""+rifOutput+"\"\nDo you want to do this?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
DumpAllRifs.setDumpAllFlagAndStartPsm(MainActivity.this);
}
})
.setNegativeButton("No", null).show();
}
}

View File

@ -11,14 +11,17 @@ import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Locale;
import eu.chainfire.libsuperuser.Shell;
@ -30,10 +33,13 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
private String errorMsg = "";
private ProgressDialog dialog = null;
private Context ctx = null;
private Handler handler = null;
private StringEncryptor stringEncryptor = null;
public NoPsmDrmInstaller(Context context){
this.ctx = context;
this.handler = new Handler(ctx.getMainLooper());
this.stringEncryptor = new StringEncryptor(this.ctx);
}
@ -98,27 +104,50 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
writer.close();
}
private void backupPsm() throws Exception {
private void backupPsm() throws Exception {
String psmFilesDir = new File(getPsmApp().dataDir, "files").getAbsolutePath();
String psmKdcDir = new File(psmFilesDir, "kdc").getAbsolutePath();
String psmActFile = new File(psmKdcDir, "act.dat").getAbsolutePath();
String psmAndroidFolder = new File(new File(new File(new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data"), "com.playstation.psstore"), "files"), "psm").getAbsolutePath();
String psmSdcardFolder = new File(Environment.getExternalStorageDirectory(), "psm").getAbsolutePath();
// check if "act.dat" exists -- they've been here before ...
if(fileExistRoot(psmActFile)) {
String psmSdcardFolder = new File(Environment.getExternalStorageDirectory(), "psm").getAbsolutePath();
String devinfoFile = new File(ctx.getCacheDir(), "devinfo.txt").getAbsolutePath();
String tarFilename = new File(psmSdcardFolder, "psm_"+getDateTime() + ".tar").getAbsolutePath();
// check if "act.dat" exists -- they've used PSM before ...
if(Root.fileExistRoot(psmActFile)) {
new File(psmSdcardFolder).mkdirs();
String filename = "psm_"+getDateTime();
// tar up the files
tarRoot(getPsmApp().dataDir,new File(psmSdcardFolder, filename+".tar").getAbsolutePath());
File psmAndroidFile = new File(psmAndroidFolder);
// generate device fingerprint file
generateDeviceFingerprint(new File(psmSdcardFolder, filename + "_DEV.txt").getAbsolutePath());
generateDeviceFingerprint(devinfoFile);
ArrayList<String> filesToTar = new ArrayList<String>();
filesToTar.add(getPsmApp().dataDir);
filesToTar.add(devinfoFile);
// add all license folders ....
if(psmAndroidFile.exists()){
for(String gameFolder : psmAndroidFile.list()){
File licenseFolder = new File(new File(psmAndroidFile, gameFolder), "License");
if(licenseFolder.exists()){
filesToTar.add(licenseFolder.toString());
}
}
}
// tar up the files
tarRoot(filesToTar, tarFilename);
handler.post(() -> {
Toast.makeText(ctx.getApplicationContext(),"Backed up existing PSM Data to:\n\""+tarFilename+"\"", Toast.LENGTH_LONG).show();
});
}
}
private void makeDirs() throws PackageManager.NameNotFoundException, Shell.ShellDiedException {
mkdirAndChmodChown(new File(getPsmApp().dataDir, "cache").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid()));
mkdirAndChmodChown(new File(getPsmApp().dataDir, "shared_prefs").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid()));
@ -133,8 +162,8 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
// check if signininfo.xml file exists or not ...
boolean signinInfoExist = fileExistRoot(new File(sharedPrefsPath, "SigninInfo.xml").getAbsolutePath());
if (!signinInfoExist) { // if file not found ...
// then generate our own shared_prefs
if (!signinInfoExist) { // if no psmdrm activation file was found
// then generate our own shared_prefs
// encrypt the actual strings, username, password, etc
String emailAddress = stringEncryptor.encryptString(Helper.sharedPrefs.getString("saveAccountEmail","nopsmdrm@transrights.lgbt"));
@ -242,10 +271,11 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
}
@Override
protected void onPreExecute() {
Shell.setRedirectDeprecated(false);
dialog = new ProgressDialog(ctx);
dialog.setTitle("Installing NoPsmDrm ...");
if(!Helper.isNoPsmDrmAlreadyInstalled())
dialog.setTitle("Installing NoPsmDrm ...");
else
dialog.setTitle("Updating NoPsmDrm ...");
dialog.setMessage("Please Wait ...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
@ -258,7 +288,7 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
try {
Root.setContext(ctx);
killApplication("com.playstation.psstore");
Helper.killPsm();
if (isPsmInstalled()) {
backupPsm();
@ -295,7 +325,7 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
}
else{
new AlertDialog.Builder((Activity)ctx)
.setTitle("Installed!")
.setTitle("Finished!")
.setMessage("Your PSM Application was patched successfully!\n\nNote: WI-FI has to be turned off for games to work.")
.setCancelable(false)
.setPositiveButton("Ok", null).show();

View File

@ -9,6 +9,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import eu.chainfire.libsuperuser.Shell;
@ -16,9 +17,9 @@ public class Root {
private static String busyboxBinary = null;
private static Context ctx = null;
public static void killApplication(String processName) throws Shell.ShellDiedException {
Log.i("ROOT", "Killing process: " + processName);
Shell.Pool.SU.run(new String[] { busyboxBinary + " pkill -9 '" + processName +"'" });
public static void reboot() throws Shell.ShellDiedException {
Log.i("ROOT", "Rebooting");
Shell.Pool.SU.run(new String[] { busyboxBinary + " reboot" });
}
public static boolean fileExistRoot(String filename) throws Shell.ShellDiedException {
Log.i("ROOT", "FileExistRoot: " + filename);
@ -26,12 +27,24 @@ public class Root {
return res == 0;
}
public static void tarRoot(String src, String dst) throws IOException, Shell.ShellDiedException {
Log.i("ROOT", "TarRoot: " + src + " : "+ dst);
int res = Shell.Pool.SU.run(new String[]{busyboxBinary + " tar c '" + src + "' -f '" + dst +"'"});
public static void tarRoot(ArrayList<String> src, String dst) throws IOException, Shell.ShellDiedException {
if(src.size() <= 0){
throw new IOException("tar src was empty.");
};
Log.i("ROOT", "TarRoot: "+ dst);
StringBuilder tarFiles = new StringBuilder();
for(String file : src) {
tarFiles.append("'");
tarFiles.append(file);
tarFiles.append("' ");
}
int res = Shell.Pool.SU.run(new String[]{busyboxBinary + " tar -cf '" + dst + "' "+tarFiles.toString()});
if (res != 0) {
Log.e("ROOT", "error (" + String.valueOf(res) +")");
throw new IOException("Failed to tar " + src);
throw new IOException("Failed to tar " + dst);
}
}
public static void remountRo(String foldername) throws IOException, Shell.ShellDiedException {
@ -136,6 +149,7 @@ public class Root {
public static void setContext(Context context) throws IOException {
ctx = context;
Shell.setRedirectDeprecated(false);
setupBusyBox();
}
}

View File

@ -5,12 +5,16 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.widget.Button;
import android.widget.TextView;
import eu.chainfire.libsuperuser.Shell;
import static com.psmreborn.nopsmdrm.Helper.*;
import com.psmreborn.nopsmdrm.pscertified.PlayStationCertified;
import com.psmreborn.nopsmdrm.pscertified.PsCertificatesInstaller;
import java.io.File;
public class Startup extends AsyncTask<Void, Void, Void> {
@ -29,20 +33,26 @@ public class Startup extends AsyncTask<Void, Void, Void> {
if(!Shell.SU.available()){
wasError = true;
errorMsg = "Unable to get root permission.";
return null;
}
if(!Helper.isPsmInstalled()){
wasError = true;
errorMsg = "PSM Application is not installed, please install it first!";
return null;
}
if(!(getPsmApp().sourceDir.startsWith("/data/") || getPsmApp().sourceDir.startsWith("/system/"))){
wasError = true;
errorMsg = "PSM Application is installed to the SD Card not internal storage.";
return null;
}
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
wasError = true;
errorMsg = "No SD Card inserted.";
return null;
}
Root.setContext(this.ctx);
} catch (Exception e) {
wasError = true;
errorMsg = e.getMessage();
@ -54,19 +64,25 @@ public class Startup extends AsyncTask<Void, Void, Void> {
protected void onPostExecute(Void result) {
TextView statusTV = (TextView) ((Activity)ctx).findViewById(R.id.errorMsg);
Button installButton = (Button) ((Activity)ctx).findViewById(R.id.installPsm);
Button backupGamesButton = (Button) ((Activity)ctx).findViewById(R.id.dumpGames);
Handler handler = new Handler(this.ctx.getMainLooper());
if(!wasError) {
statusTV.setText("");
handler.post(() -> {
statusTV.setText("");
if(isNoPsmDrmAlreadyInstalled()){
installButton.setText("Update NoPsmDrm");
};
installButton.setEnabled(true);
if(Helper.isNoPsmDrmAlreadyInstalled()){
installButton.setText("Update NoPsmDrm");
};
installButton.setEnabled(true);
backupGamesButton.setEnabled(true);
});
}
else{
statusTV.setText("Error: "+errorMsg);
handler.post(() -> {
statusTV.setText("Error: " + errorMsg);
});
}
}
}

View File

@ -13,6 +13,7 @@ import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.PowerManager;
@ -84,9 +85,20 @@ public class PsCertificatesInstaller extends AsyncTask<Void, Void, Void> {
else{
new AlertDialog.Builder((Activity)ctx)
.setTitle("Installed!")
.setMessage("Your device is now \"Playstation Certified\"\n(You may have to reboot for changes to take effect)")
.setMessage("Your device is now \"Playstation Certified\"\n(You have to reboot for changes to take effect)\nReboot?")
.setCancelable(false)
.setPositiveButton("Ok",null).show();
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Handler handler = new Handler(PsCertificatesInstaller.this.ctx.getMainLooper());
handler.post(() -> {
try {
Root.reboot();
} catch (Shell.ShellDiedException e) {}
});
}
})
.setNegativeButton("No", null).show();
}
}
}

View File

@ -29,4 +29,15 @@
android:layout_below="@+id/errorMsg"
android:text="Install NoPsmDrm"/>
<Button
android:id="@+id/dumpGames"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:onClick="dumpAllRifs"
android:textSize="30sp"
android:enabled="false"
android:layout_below="@+id/installPsm"
android:text="Backup all licenses"/>
</RelativeLayout>

Binary file not shown.

View File

@ -1,3 +1,3 @@
<resources>
<string name="app_name">NoPsmDrm Installer</string>
<string name="app_name">NoPsmDrm</string>
</resources>

View File

@ -12,7 +12,7 @@ android {
buildTypes {
release {
minifyEnabled false
minifyEnabled true
}
}
compileOptions {