Move shared AIDL files into lib, restructure, start of install/delete code
This commit is contained in:
parent
09cdb08fdb
commit
85c8e7035d
@ -1,14 +1,9 @@
|
|||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
jcenter()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.android.tools.build:gradle:1.3.1'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(':privileged-api-lib')
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 22
|
compileSdkVersion 22
|
||||||
buildToolsVersion '23.0.0'
|
buildToolsVersion '23.0.0'
|
||||||
|
@ -51,11 +51,7 @@
|
|||||||
android:maxSdkVersion="18" />
|
android:maxSdkVersion="18" />
|
||||||
<uses-permission android:name="android.permission.NFC" />
|
<uses-permission android:name="android.permission.NFC" />
|
||||||
|
|
||||||
<!-- These permissions are only granted when F-Droid is installed as a system-app! -->
|
<uses-permission android:name="org.fdroid.fdroid.privileged.USE_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.INSTALL_PACKAGES"
|
|
||||||
tools:ignore="ProtectedPermissions"/>
|
|
||||||
<uses-permission android:name="android.permission.DELETE_PACKAGES"
|
|
||||||
tools:ignore="ProtectedPermissions"/>
|
|
||||||
|
|
||||||
<!-- Indicate that F-Droid may request root access (introduced by Koush's Superuser app)
|
<!-- Indicate that F-Droid may request root access (introduced by Koush's Superuser app)
|
||||||
This permission is deprecated, but necessary for some old superuser
|
This permission is deprecated, but necessary for some old superuser
|
||||||
|
@ -15,6 +15,7 @@ if ( !hasProperty( 'sourceDeps' ) ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
compile project(':privileged-api-lib')
|
||||||
|
|
||||||
compile 'com.android.support:support-v4:22.2.1'
|
compile 'com.android.support:support-v4:22.2.1'
|
||||||
compile 'com.android.support:appcompat-v7:22.1.1'
|
compile 'com.android.support:appcompat-v7:22.1.1'
|
||||||
@ -60,6 +61,7 @@ if ( !hasProperty( 'sourceDeps' ) ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
compile project(':privileged-api-lib')
|
||||||
compile project(':extern:AndroidPinning')
|
compile project(':extern:AndroidPinning')
|
||||||
compile project(':extern:UniversalImageLoader:library')
|
compile project(':extern:UniversalImageLoader:library')
|
||||||
compile project(':extern:libsuperuser:libsuperuser')
|
compile project(':extern:libsuperuser:libsuperuser')
|
||||||
|
@ -21,25 +21,28 @@
|
|||||||
package org.fdroid.fdroid.installer;
|
package org.fdroid.fdroid.installer;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.IPackageDeleteObserver;
|
|
||||||
import android.content.pm.IPackageInstallObserver;
|
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
|
import org.fdroid.fdroid.privileged.IPrivilegedCallback;
|
||||||
|
import org.fdroid.fdroid.privileged.IPrivilegedService;
|
||||||
import org.fdroid.fdroid.privileged.views.AppDiff;
|
import org.fdroid.fdroid.privileged.views.AppDiff;
|
||||||
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
|
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
|
||||||
import org.fdroid.fdroid.privileged.views.InstallConfirmActivity;
|
import org.fdroid.fdroid.privileged.views.InstallConfirmActivity;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,11 +73,10 @@ public class PrivilegedInstaller extends Installer {
|
|||||||
|
|
||||||
private static final String TAG = "PrivilegedInstaller";
|
private static final String TAG = "PrivilegedInstaller";
|
||||||
|
|
||||||
|
private static final String PRIVILEGED_INTENT = "org.fdroid.fdroid.privileged.IPrivilegedService";
|
||||||
|
private static final String PRIVILEGED_PACKAGE_NAME = "org.fdroid.fdroid.privileged";
|
||||||
|
|
||||||
private Activity mActivity;
|
private Activity mActivity;
|
||||||
// private final PackageInstallObserver mInstallObserver;
|
|
||||||
// private final PackageDeleteObserver mDeleteObserver;
|
|
||||||
// private Method mInstallMethod;
|
|
||||||
// private Method mDeleteMethod;
|
|
||||||
|
|
||||||
public static final int REQUEST_CONFIRM_PERMS = 0;
|
public static final int REQUEST_CONFIRM_PERMS = 0;
|
||||||
|
|
||||||
@ -83,61 +85,6 @@ public class PrivilegedInstaller extends Installer {
|
|||||||
super(activity, pm, callback);
|
super(activity, pm, callback);
|
||||||
this.mActivity = activity;
|
this.mActivity = activity;
|
||||||
|
|
||||||
// create internal callbacks
|
|
||||||
mInstallObserver = new PackageInstallObserver();
|
|
||||||
mDeleteObserver = new PackageDeleteObserver();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Class<?>[] installTypes = {
|
|
||||||
Uri.class, IPackageInstallObserver.class, int.class,
|
|
||||||
String.class
|
|
||||||
};
|
|
||||||
Class<?>[] deleteTypes = {
|
|
||||||
String.class, IPackageDeleteObserver.class,
|
|
||||||
int.class
|
|
||||||
};
|
|
||||||
|
|
||||||
mInstallMethod = mPm.getClass().getMethod("installPackage", installTypes);
|
|
||||||
mDeleteMethod = mPm.getClass().getMethod("deletePackage", deleteTypes);
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
throw new AndroidNotCompatibleException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal install callback from the system
|
|
||||||
*/
|
|
||||||
class PackageInstallObserver extends IPackageInstallObserver.Stub {
|
|
||||||
public void packageInstalled(String packageName, int returnCode) throws RemoteException {
|
|
||||||
// TODO: propagate other return codes?
|
|
||||||
if (returnCode == INSTALL_SUCCEEDED) {
|
|
||||||
Utils.DebugLog(TAG, "Install succeeded");
|
|
||||||
|
|
||||||
mCallback.onSuccess(InstallerCallback.OPERATION_INSTALL);
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Install failed with returnCode " + returnCode);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal delete callback from the system
|
|
||||||
*/
|
|
||||||
class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
|
|
||||||
public void packageDeleted(String packageName, int returnCode) throws RemoteException {
|
|
||||||
// TODO: propagate other return codes?
|
|
||||||
if (returnCode == DELETE_SUCCEEDED) {
|
|
||||||
Utils.DebugLog(TAG, "Delete succeeded");
|
|
||||||
|
|
||||||
mCallback.onSuccess(InstallerCallback.OPERATION_DELETE);
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Delete failed with returnCode " + returnCode);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_DELETE,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -179,15 +126,47 @@ public class PrivilegedInstaller extends Installer {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doInstallPackageInternal(Uri packageURI) throws AndroidNotCompatibleException {
|
private void doInstallPackageInternal(final Uri packageURI) throws AndroidNotCompatibleException {
|
||||||
try {
|
ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||||
mInstallMethod.invoke(mPm, packageURI, mInstallObserver,
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
INSTALL_REPLACE_EXISTING, null);
|
IPrivilegedService privService = IPrivilegedService.Stub.asInterface(service);
|
||||||
} catch (Exception e) {
|
|
||||||
throw new AndroidNotCompatibleException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
IPrivilegedCallback callback = new IPrivilegedCallback() {
|
||||||
|
@Override
|
||||||
|
public void handleResult(String packageName, int returnCode) throws RemoteException {
|
||||||
|
// TODO: propagate other return codes?
|
||||||
|
if (returnCode == INSTALL_SUCCEEDED) {
|
||||||
|
Utils.DebugLog(TAG, "Install succeeded");
|
||||||
|
mCallback.onSuccess(InstallerCallback.OPERATION_INSTALL);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Install failed with returnCode " + returnCode);
|
||||||
|
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
||||||
|
InstallerCallback.ERROR_CODE_OTHER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder asBinder() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
privService.installPackage(packageURI, INSTALL_REPLACE_EXISTING, null, callback);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "RemoteException", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Intent serviceIntent = new Intent(PRIVILEGED_INTENT);
|
||||||
|
serviceIntent.setPackage(PRIVILEGED_PACKAGE_NAME);
|
||||||
|
mContext.getApplicationContext().bindService(serviceIntent, mServiceConnection,
|
||||||
|
Context.BIND_AUTO_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installPackageInternal(List<File> apkFiles)
|
protected void installPackageInternal(List<File> apkFiles)
|
||||||
@ -253,35 +232,70 @@ public class PrivilegedInstaller extends Installer {
|
|||||||
|
|
||||||
private void doDeletePackageInternal(final String packageName)
|
private void doDeletePackageInternal(final String packageName)
|
||||||
throws AndroidNotCompatibleException {
|
throws AndroidNotCompatibleException {
|
||||||
try {
|
ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||||
mDeleteMethod.invoke(mPm, packageName, mDeleteObserver, 0);
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
} catch (Exception e) {
|
IPrivilegedService privService = IPrivilegedService.Stub.asInterface(service);
|
||||||
throw new AndroidNotCompatibleException(e);
|
|
||||||
}
|
IPrivilegedCallback callback = new IPrivilegedCallback() {
|
||||||
|
@Override
|
||||||
|
public void handleResult(String packageName, int returnCode) throws RemoteException {
|
||||||
|
// TODO: propagate other return codes?
|
||||||
|
if (returnCode == DELETE_SUCCEEDED) {
|
||||||
|
Utils.DebugLog(TAG, "Delete succeeded");
|
||||||
|
|
||||||
|
mCallback.onSuccess(InstallerCallback.OPERATION_DELETE);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Delete failed with returnCode " + returnCode);
|
||||||
|
mCallback.onError(InstallerCallback.OPERATION_DELETE,
|
||||||
|
InstallerCallback.ERROR_CODE_OTHER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder asBinder() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
privService.deletePackage(packageName, 0, callback);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "RemoteException", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Intent serviceIntent = new Intent(PRIVILEGED_INTENT);
|
||||||
|
serviceIntent.setPackage(PRIVILEGED_PACKAGE_NAME);
|
||||||
|
mContext.getApplicationContext().bindService(serviceIntent, mServiceConnection,
|
||||||
|
Context.BIND_AUTO_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handleOnActivityResult(int requestCode, int resultCode, Intent data) {
|
public boolean handleOnActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_CONFIRM_PERMS:
|
case REQUEST_CONFIRM_PERMS:
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
final Uri packageUri = data.getData();
|
final Uri packageUri = data.getData();
|
||||||
try {
|
try {
|
||||||
doInstallPackageInternal(packageUri);
|
doInstallPackageInternal(packageUri);
|
||||||
} catch (AndroidNotCompatibleException e) {
|
} catch (AndroidNotCompatibleException e) {
|
||||||
|
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
||||||
|
InstallerCallback.ERROR_CODE_OTHER);
|
||||||
|
}
|
||||||
|
} else if (resultCode == InstallConfirmActivity.RESULT_CANNOT_PARSE) {
|
||||||
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
InstallerCallback.ERROR_CODE_CANNOT_PARSE);
|
||||||
|
} else { // Activity.RESULT_CANCELED
|
||||||
|
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
||||||
|
InstallerCallback.ERROR_CODE_CANCELED);
|
||||||
}
|
}
|
||||||
} else if (resultCode == InstallConfirmActivity.RESULT_CANNOT_PARSE) {
|
return true;
|
||||||
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
default:
|
||||||
InstallerCallback.ERROR_CODE_CANNOT_PARSE);
|
return false;
|
||||||
} else { // Activity.RESULT_CANCELED
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
|
||||||
InstallerCallback.ERROR_CODE_CANCELED);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,7 +596,7 @@ public class PrivilegedInstaller extends Installer {
|
|||||||
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
|
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
|
||||||
* if the system failed to install the package because it is attempting to define a
|
* if the system failed to install the package because it is attempting to define a
|
||||||
* permission that is already defined by some existing package.
|
* permission that is already defined by some existing package.
|
||||||
*
|
* <p/>
|
||||||
* <p>The package name of the app which has already defined the permission is passed to
|
* <p>The package name of the app which has already defined the permission is passed to
|
||||||
* a {@link PackageInstallObserver}, if any, as the {@link #EXTRA_EXISTING_PACKAGE}
|
* a {@link PackageInstallObserver}, if any, as the {@link #EXTRA_EXISTING_PACKAGE}
|
||||||
* string extra; and the name of the permission being redefined is passed in the
|
* string extra; and the name of the permission being redefined is passed in the
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.fdroid.fdroid.privileged;
|
|
||||||
|
|
||||||
interface IPrivilegedCallback {
|
|
||||||
|
|
||||||
void handleResult(in String packageName, in int returnCode);
|
|
||||||
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.fdroid.fdroid.privileged;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.privileged.IPrivilegedCallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronous (oneway) IPC calls!
|
|
||||||
*/
|
|
||||||
oneway interface IPrivilegedService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Docs based on PackageManager.installPackage()
|
|
||||||
*
|
|
||||||
* Install a package. Since this may take a little while, the result will
|
|
||||||
* be posted back to the given callback. An installation will fail if the
|
|
||||||
* package named in the package file's manifest is already installed, or if there's no space
|
|
||||||
* available on the device.
|
|
||||||
*
|
|
||||||
* @param packageURI The location of the package file to install. This can be a 'file:' or a
|
|
||||||
* 'content:' URI.
|
|
||||||
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
|
|
||||||
* {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
|
|
||||||
* @param installerPackageName Optional package name of the application that is performing the
|
|
||||||
* installation. This identifies which market the package came from.
|
|
||||||
* @param callback An callback to get notified when the package installation is
|
|
||||||
* complete.
|
|
||||||
*/
|
|
||||||
void installPackage(in Uri packageURI, in int flags, in String installerPackageName,
|
|
||||||
in IPrivilegedCallback callback);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Docs based on PackageManager.deletePackage()
|
|
||||||
*
|
|
||||||
* Attempts to delete a package. Since this may take a little while, the result will
|
|
||||||
* be posted back to the given observer. A deletion will fail if the
|
|
||||||
* named package cannot be found, or if the named package is a "system package".
|
|
||||||
*
|
|
||||||
* @param packageName The name of the package to delete
|
|
||||||
* @param flags - possible values: {@link #DELETE_KEEP_DATA},
|
|
||||||
* {@link #DELETE_ALL_USERS}.
|
|
||||||
* @param callback An callback to get notified when the package deletion is
|
|
||||||
* complete.
|
|
||||||
*/
|
|
||||||
void deletePackage(in String packageName, in int flags, in IPrivilegedCallback callback);
|
|
||||||
|
|
||||||
}
|
|
33
Privileged-F-Droid/.gitignore
vendored
33
Privileged-F-Droid/.gitignore
vendored
@ -1,33 +0,0 @@
|
|||||||
#Android specific
|
|
||||||
bin
|
|
||||||
gen
|
|
||||||
obj
|
|
||||||
lint.xml
|
|
||||||
local.properties
|
|
||||||
release.properties
|
|
||||||
ant.properties
|
|
||||||
*.class
|
|
||||||
*.apk
|
|
||||||
|
|
||||||
#Gradle
|
|
||||||
.gradle
|
|
||||||
build
|
|
||||||
gradle.properties
|
|
||||||
|
|
||||||
#Maven
|
|
||||||
target
|
|
||||||
pom.xml.*
|
|
||||||
|
|
||||||
#Eclipse
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
.settings
|
|
||||||
.metadata
|
|
||||||
|
|
||||||
#IntelliJ IDEA
|
|
||||||
.idea
|
|
||||||
*.iml
|
|
||||||
|
|
||||||
#Lint output
|
|
||||||
lint-report.html
|
|
||||||
lint-report_files/*
|
|
@ -1,51 +0,0 @@
|
|||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
jcenter()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.android.tools.build:gradle:1.3.1'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 22
|
|
||||||
buildToolsVersion '23.0.0'
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdkVersion 8
|
|
||||||
targetSdkVersion 22
|
|
||||||
versionCode 1
|
|
||||||
versionName "1.0"
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
compileOptions.encoding = "UTF-8"
|
|
||||||
|
|
||||||
// Use Java 1.7, requires minSdk 8
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_7
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_7
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled true
|
|
||||||
|
|
||||||
// Reference them in the java files with e.g. BuildConfig.F_DROID_CERT_SHA512.
|
|
||||||
buildConfigField "String", "F_DROID_CERT_SHA512", "\"9ba5d51a0d5c3627e270c2542b761937c721b0d8a1caed88bd3b2f21add138c2f16e295ce67bef21b21e0b75d5a0c6fd13d67efeb85c198cffa365755c94f4c2\""
|
|
||||||
}
|
|
||||||
|
|
||||||
debug {
|
|
||||||
|
|
||||||
// Reference them in the java files with e.g. BuildConfig.F_DROID_CERT_SHA512.
|
|
||||||
buildConfigField "String", "F_DROID_CERT_SHA512", "\"9ba5d51a0d5c3627e270c2542b761937c721b0d8a1caed88bd3b2f21add138c2f16e295ce67bef21b21e0b75d5a0c6fd13d67efeb85c198cffa365755c94f4c2\""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lintOptions {
|
|
||||||
// Do not abort build if lint finds errors
|
|
||||||
abortOnError false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
package="org.fdroid.fdroid.privileged">
|
|
||||||
|
|
||||||
<!-- These permissions are only granted when this apk is installed as a privileged app! -->
|
|
||||||
<uses-permission
|
|
||||||
android:name="android.permission.INSTALL_PACKAGES"
|
|
||||||
tools:ignore="ProtectedPermissions" />
|
|
||||||
<uses-permission
|
|
||||||
android:name="android.permission.DELETE_PACKAGES"
|
|
||||||
tools:ignore="ProtectedPermissions" />
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Only apps signed with the same key can use this permission!
|
|
||||||
Never presented to the user due to the protectionLevel.
|
|
||||||
-->
|
|
||||||
<permission
|
|
||||||
android:name="org.fdroid.fdroid.privileged.USE_SERVICE"
|
|
||||||
android:protectionLevel="signature" />
|
|
||||||
|
|
||||||
<application
|
|
||||||
android:allowBackup="false"
|
|
||||||
android:icon="@drawable/ic_launcher"
|
|
||||||
android:label="@string/app_name">
|
|
||||||
|
|
||||||
<!-- API -->
|
|
||||||
<service
|
|
||||||
android:name=".PrivilegedService"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="true"
|
|
||||||
android:process=":fdroid_privileged"
|
|
||||||
android:permission="org.fdroid.fdroid.privileged.USE_SERVICE">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="org.fdroid.fdroid.privileged.IPrivilegedService" />
|
|
||||||
</intent-filter>
|
|
||||||
</service>
|
|
||||||
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.fdroid.fdroid.privileged;
|
|
||||||
|
|
||||||
interface IPrivilegedCallback {
|
|
||||||
|
|
||||||
void handleResult(in String packageName, in int returnCode);
|
|
||||||
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.fdroid.fdroid.privileged;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.privileged.IPrivilegedCallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronous (oneway) IPC calls!
|
|
||||||
*/
|
|
||||||
oneway interface IPrivilegedService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Docs based on PackageManager.installPackage()
|
|
||||||
*
|
|
||||||
* Install a package. Since this may take a little while, the result will
|
|
||||||
* be posted back to the given callback. An installation will fail if the
|
|
||||||
* package named in the package file's manifest is already installed, or if there's no space
|
|
||||||
* available on the device.
|
|
||||||
*
|
|
||||||
* @param packageURI The location of the package file to install. This can be a 'file:' or a
|
|
||||||
* 'content:' URI.
|
|
||||||
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
|
|
||||||
* {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
|
|
||||||
* @param installerPackageName Optional package name of the application that is performing the
|
|
||||||
* installation. This identifies which market the package came from.
|
|
||||||
* @param callback An callback to get notified when the package installation is
|
|
||||||
* complete.
|
|
||||||
*/
|
|
||||||
void installPackage(in Uri packageURI, in int flags, in String installerPackageName,
|
|
||||||
in IPrivilegedCallback callback);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Docs based on PackageManager.deletePackage()
|
|
||||||
*
|
|
||||||
* Attempts to delete a package. Since this may take a little while, the result will
|
|
||||||
* be posted back to the given observer. A deletion will fail if the
|
|
||||||
* named package cannot be found, or if the named package is a "system package".
|
|
||||||
*
|
|
||||||
* @param packageName The name of the package to delete
|
|
||||||
* @param flags - possible values: {@link #DELETE_KEEP_DATA},
|
|
||||||
* {@link #DELETE_ALL_USERS}.
|
|
||||||
* @param callback An callback to get notified when the package deletion is
|
|
||||||
* complete.
|
|
||||||
*/
|
|
||||||
void deletePackage(in String packageName, in int flags, in IPrivilegedCallback callback);
|
|
||||||
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package android.content.pm;
|
|
||||||
|
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.IInterface;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Just a non-working implementation of this Stub to satisfy compiler!
|
|
||||||
*/
|
|
||||||
public interface IPackageDeleteObserver extends IInterface {
|
|
||||||
|
|
||||||
abstract class Stub extends Binder implements android.content.pm.IPackageDeleteObserver {
|
|
||||||
|
|
||||||
public Stub() {
|
|
||||||
throw new RuntimeException("Stub!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IPackageDeleteObserver asInterface(IBinder obj) {
|
|
||||||
throw new RuntimeException("Stub!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBinder asBinder() {
|
|
||||||
throw new RuntimeException("Stub!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
|
|
||||||
throws RemoteException {
|
|
||||||
throw new RuntimeException("Stub!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void packageDeleted(java.lang.String packageName, int returnCode) throws RemoteException;
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package android.content.pm;
|
|
||||||
|
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.IInterface;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Just a non-working implementation of this Stub to satisfy compiler!
|
|
||||||
*/
|
|
||||||
public interface IPackageInstallObserver extends IInterface {
|
|
||||||
|
|
||||||
abstract class Stub extends Binder implements android.content.pm.IPackageInstallObserver {
|
|
||||||
|
|
||||||
public Stub() {
|
|
||||||
throw new RuntimeException("Stub!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static android.content.pm.IPackageInstallObserver asInterface(IBinder obj) {
|
|
||||||
throw new RuntimeException("Stub!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBinder asBinder() {
|
|
||||||
throw new RuntimeException("Stub!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
|
|
||||||
throws RemoteException {
|
|
||||||
throw new RuntimeException("Stub!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void packageInstalled(String packageName, int returnCode) throws RemoteException;
|
|
||||||
}
|
|
@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.fdroid.fdroid.privileged;
|
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.IPackageDeleteObserver;
|
|
||||||
import android.content.pm.IPackageInstallObserver;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This service provides an API via AIDL IPC for the main F-Droid app to install/delete packages.
|
|
||||||
*/
|
|
||||||
public class PrivilegedService extends Service {
|
|
||||||
|
|
||||||
public static final String TAG = "PrivilegedFDroid";
|
|
||||||
|
|
||||||
private Method mInstallMethod;
|
|
||||||
private Method mDeleteMethod;
|
|
||||||
|
|
||||||
private void installPackageImpl(Uri packageURI, int flags, String installerPackageName,
|
|
||||||
final IPrivilegedCallback callback) {
|
|
||||||
|
|
||||||
// Internal callback from the system
|
|
||||||
IPackageInstallObserver.Stub installObserver = new IPackageInstallObserver.Stub() {
|
|
||||||
@Override
|
|
||||||
public void packageInstalled(String packageName, int returnCode) throws RemoteException {
|
|
||||||
// forward this internal callback to our callback
|
|
||||||
try {
|
|
||||||
callback.handleResult(packageName, returnCode);
|
|
||||||
} catch (RemoteException e1) {
|
|
||||||
Log.e(TAG, "RemoteException", e1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// execute internal method
|
|
||||||
try {
|
|
||||||
mInstallMethod.invoke(getPackageManager(), packageURI, installObserver,
|
|
||||||
flags, installerPackageName);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Android not compatible!", e);
|
|
||||||
try {
|
|
||||||
callback.handleResult(null, 0);
|
|
||||||
} catch (RemoteException e1) {
|
|
||||||
Log.e(TAG, "RemoteException", e1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deletePackageImpl(String packageName, int flags, final IPrivilegedCallback callback) {
|
|
||||||
|
|
||||||
// Internal callback from the system
|
|
||||||
IPackageDeleteObserver.Stub deleteObserver = new IPackageDeleteObserver.Stub() {
|
|
||||||
@Override
|
|
||||||
public void packageDeleted(String packageName, int returnCode) throws RemoteException {
|
|
||||||
// forward this internal callback to our callback
|
|
||||||
try {
|
|
||||||
callback.handleResult(packageName, returnCode);
|
|
||||||
} catch (RemoteException e1) {
|
|
||||||
Log.e(TAG, "RemoteException", e1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// execute internal method
|
|
||||||
try {
|
|
||||||
mDeleteMethod.invoke(getPackageManager(), packageName, deleteObserver, flags);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Android not compatible!", e);
|
|
||||||
try {
|
|
||||||
callback.handleResult(null, 0);
|
|
||||||
} catch (RemoteException e1) {
|
|
||||||
Log.e(TAG, "RemoteException", e1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final IPrivilegedService.Stub mBinder = new IPrivilegedService.Stub() {
|
|
||||||
@Override
|
|
||||||
public void installPackage(Uri packageURI, int flags, String installerPackageName,
|
|
||||||
IPrivilegedCallback callback) {
|
|
||||||
installPackageImpl(packageURI, flags, installerPackageName, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deletePackage(String packageName, int flags, IPrivilegedCallback callback) {
|
|
||||||
deletePackageImpl(packageName, flags, callback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return mBinder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
|
|
||||||
// get internal methods via reflection
|
|
||||||
try {
|
|
||||||
Class<?>[] installTypes = {
|
|
||||||
Uri.class, IPackageInstallObserver.class, int.class,
|
|
||||||
String.class
|
|
||||||
};
|
|
||||||
Class<?>[] deleteTypes = {
|
|
||||||
String.class, IPackageDeleteObserver.class,
|
|
||||||
int.class
|
|
||||||
};
|
|
||||||
|
|
||||||
PackageManager pm = getPackageManager();
|
|
||||||
mInstallMethod = pm.getClass().getMethod("installPackage", installTypes);
|
|
||||||
mDeleteMethod = pm.getClass().getMethod("deletePackage", deleteTypes);
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
Log.e(TAG, "Android not compatible!", e);
|
|
||||||
stopSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<string name="app_name">F-Droid Privileged</string>
|
|
||||||
|
|
||||||
</resources>
|
|
18
privileged-api-lib/build.gradle
Normal file
18
privileged-api-lib/build.gradle
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 22
|
||||||
|
buildToolsVersion '23.0.0'
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 8
|
||||||
|
targetSdkVersion 22
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not abort build if lint finds errors
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
}
|
6
privileged-api-lib/src/main/AndroidManifest.xml
Normal file
6
privileged-api-lib/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest package="org.fdroid.fdroid.privileged.api">
|
||||||
|
|
||||||
|
<application />
|
||||||
|
|
||||||
|
</manifest>
|
@ -1,4 +1,6 @@
|
|||||||
include ':F-Droid'
|
include ':F-Droid'
|
||||||
|
include ':F-Droid-Privileged'
|
||||||
|
include ':privileged-api-lib'
|
||||||
|
|
||||||
if ( hasProperty( 'sourceDeps' ) ) {
|
if ( hasProperty( 'sourceDeps' ) ) {
|
||||||
include ':extern:AndroidPinning'
|
include ':extern:AndroidPinning'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user