package com.pekall.backup;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import com.pekall.backup.backupservicetestapp.Slog;
public class Backup {
private int mNativeContext;
private Context mContext;
static {
System.loadLibrary("backup_jni");
native_init();
}
public Backup(Context context) {
mContext = context;
/*
* Native setup requires a weak reference to our object. It's easier to
* create it here than in C++.
*/
native_setup(new WeakReference<Backup>(this));
}
public void release() {
native_release();
mContext = null;
}
private static native final void native_init();
private native final void native_setup(Object backup_this);
private native final void native_release();
private native final String native_getDirOwnerStr(String packageName);
/**
* Get the user name and group name for app package's private data directory
*
* @param packageName
* @return [user name, group name] pair
*/
public String[] getPackageUnameGname(String packageName) {
String dirOwnerStr = native_getDirOwnerStr(packageName);
Slog.d("dirOwnerStr = " + dirOwnerStr);
if (dirOwnerStr == null || dirOwnerStr.length() == 0) {
return null;
}
Pattern pattern = Pattern.compile("[drwx\\-]{10}\\s+(\\w+)\\s+(\\w+)");
Matcher matcher = pattern.matcher(dirOwnerStr);
String username = null, groupname = null;
if (matcher.find()) {
username = matcher.group(1);
groupname = matcher.group(2);
}
if (username == null || groupname == null) {
return null;
}
return new String[] {
username, groupname
};
}
/**
* Backup app's private data to dstDir <br/>
* <br/>
* <b>NOTICE: </b> this method may cost some time depending on the data size
* that need to be backup.
* @param backupDir where the backup file reside
* @param packageName which package's data need to be backup
*
* @return true if success, otherwise false
*/
public boolean backupData(String backupDir, String packageName) {
PackageManager pm = mContext.getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_SHARED_LIBRARY_FILES);
} catch (NameNotFoundException e) {
Slog.e("Error: cannot find pacakge: " + packageName, e);
return false;
}
String nativeLibraryDir = appInfo.nativeLibraryDir;
String dataDir = appInfo.dataDir;
String sourceDir = appInfo.sourceDir;
String[] sharedLibraryFiles = appInfo.sharedLibraryFiles;
Slog.d(String.format("nativeLibraryDir: %s, sharedLibraryFiles: %s, dataDir: %s, sourceDir: %s",
nativeLibraryDir, Arrays.toString(sharedLibraryFiles), dataDir, sourceDir));
return native_backupData(packageName, backupDir);
}
private native boolean native_backupData(String packageName, String backupDir);
/**
* Restore app's private data from srcDir to system <br/>
* <br/>
* <b>NOTICE: </b> this method may cost some time depending on the data size
* that need to be restored.
*
* @param backupDir where the backup files reside
* @param packageName which package's data need to be restored
* @return true if success, otherwise false
*/
public boolean restoreData(String backupDir, String packageName) {
int packageUid = getPackageOwnerUid(packageName);
int systemUid = getSystemUid();
if (packageUid == -1 || systemUid == -1) {
return false;
}
return native_restoreData(backupDir, packageName, packageUid, systemUid, true);
}
/**
* Get package owner's uid
*
* @param packageName
* @return the uid of the package owner or <b>-1</b> if the package is not found
*/
private int getPackageOwnerUid(String packageName) {
PackageManager pm = mContext.getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
Slog.e("Error: package not found: " + packageName, e);
return -1;
}
int uid = appInfo.uid;
Slog.d("packageName: " + packageName + ", uid: " + uid);
return uid;
}
/**
* Get the uid of <b>system</b> user
*
* @return the uid of <b>system</b> user
*/
private int getSystemUid() {
return getPackageOwnerUid("com.android.settings");
}
private native boolean native_restoreData(String backupDir, String packageName, int packageUid, int systemUid,
boolean overwrite);
}