Add Support for Aurora Services as Installation Client

This commit is contained in:
Mr.Dragon
2018-09-13 02:32:40 +05:30
parent 12cf610cda
commit ff47e4fe55
10 changed files with 218 additions and 21 deletions

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2015-2016 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.aurora.services;
interface IPrivilegedCallback {
void handleResult(in String packageName, in int returnCode);
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2015-2016 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.aurora.services;
import com.aurora.services.IPrivilegedCallback;
interface IPrivilegedService {
boolean hasPrivilegedPermissions();
/**
* - Docs based on PackageManager.installPackage()
* - Asynchronous (oneway) IPC calls!
*
* 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.
*/
oneway void installPackage(in Uri packageURI, in int flags, in String installerPackageName,
in IPrivilegedCallback callback);
/**
* - Docs based on PackageManager.deletePackage()
* - Asynchronous (oneway) IPC calls!
*
* 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.
*/
oneway void deletePackage(in String packageName, in int flags, in IPrivilegedCallback callback);
}

View File

@@ -35,6 +35,7 @@ public class Aurora {
public static final String PREFERENCE_SWIPE_PAGES = "PREFERENCE_SWIPE_PAGES";
public static final String PREFERENCE_COLOR_NAV = "PREFERENCE_COLOR_NAV";
public static final String PREFERENCE_SHOW_IME = "PREFERENCE_SHOW_IME";
public static final String INSTALLATION_METHOD_AURORA = "AURORA";
public static final String INSTALLATION_METHOD_ROOT = "ROOT";
public static final String INSTALLATION_METHOD_PRIVILEGED = "PRIVILEGED";
public static final String INSTALLATION_METHOD_DEFAULT = "DEFAULT";

View File

@@ -0,0 +1,106 @@
package com.dragons.aurora;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.aurora.services.IPrivilegedCallback;
import com.aurora.services.IPrivilegedService;
import com.dragons.aurora.model.App;
public class InstallerAurora extends InstallerAbstract {
public static final String PRIVILEGED_EXTENSION_PACKAGE_NAME = "com.aurora.services";
public static final int ACTION_INSTALL_REPLACE_EXISTING = 2;
private static final String PRIVILEGED_EXTENSION_SERVICE_INTENT = "com.aurora.services.IPrivilegedService";
public InstallerAurora(Context context) {
super(context);
}
private static boolean isExtensionInstalled(Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(PRIVILEGED_EXTENSION_PACKAGE_NAME, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
public static boolean isExtensionAvailable(Context context) {
if (!isExtensionInstalled(context)) {
return false;
}
ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
}
public void onServiceDisconnected(ComponentName name) {
}
};
Intent serviceIntent = new Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT);
serviceIntent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME);
try {
context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
return true;
} catch (SecurityException e) {
return false;
}
}
@Override
public boolean verify(App app) {
if (!super.verify(app)) {
return false;
}
return isExtensionAvailable(context);
}
@Override
protected void install(final App app) {
InstallationState.setInstalling(app.getPackageName());
ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder) {
IPrivilegedService service = IPrivilegedService.Stub.asInterface(binder);
IPrivilegedCallback callback = new IPrivilegedCallback.Stub() {
@Override
public void handleResult(String packageName, int returnCode) throws RemoteException {
Log.i(getClass().getSimpleName(), "Installation of " + packageName + " complete with code " + returnCode);
sendBroadcast(packageName, returnCode > 0);
}
};
try {
if (!service.hasPrivilegedPermissions()) {
Log.e(getClass().getSimpleName(), "service.hasPrivilegedPermissions() is false");
sendBroadcast(app.getPackageName(), false);
return;
}
service.installPackage(
Uri.fromFile(Paths.getApkPath(context, app.getPackageName(), app.getVersionCode())),
ACTION_INSTALL_REPLACE_EXISTING,
BuildConfig.APPLICATION_ID,
callback
);
} catch (RemoteException e) {
Log.e(getClass().getSimpleName(), "Connecting to privileged service failed");
sendBroadcast(app.getPackageName(), false);
}
}
public void onServiceDisconnected(ComponentName name) {
}
};
Intent serviceIntent = new Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT);
serviceIntent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME);
context.getApplicationContext().bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
}

View File

@@ -30,6 +30,8 @@ public class InstallerFactory {
static public InstallerAbstract get(Context context) {
String userChoice = Prefs.getString(context, Aurora.PREFERENCE_INSTALLATION_METHOD);
switch (userChoice) {
case Aurora.INSTALLATION_METHOD_AURORA:
return new InstallerAurora(context);
case Aurora.INSTALLATION_METHOD_PRIVILEGED:
return new InstallerPrivileged(context);
case Aurora.INSTALLATION_METHOD_ROOT:

View File

@@ -24,10 +24,11 @@ package com.dragons.aurora.fragment.preference;
import android.Manifest;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.widget.Toast;
import com.dragons.aurora.Aurora;
import com.dragons.aurora.BuildConfig;
import com.dragons.aurora.ContextUtil;
import com.dragons.aurora.InstallerAurora;
import com.dragons.aurora.R;
import com.dragons.aurora.fragment.PreferenceFragment;
import com.dragons.aurora.model.App;
@@ -50,7 +51,12 @@ class OnInstallationMethodChangeListener implements Preference.OnPreferenceChang
public boolean onPreferenceChange(Preference preference, Object newValue) {
String oldValue = ((ListPreference) preference).getValue();
if (null != oldValue && !oldValue.equals(newValue)) {
if (Aurora.INSTALLATION_METHOD_PRIVILEGED.equals(newValue)) {
if (Aurora.INSTALLATION_METHOD_AURORA.equals(newValue)) {
if (!InstallerAurora.isExtensionAvailable(activity.getActivity())) {
ContextUtil.toast(activity.getActivity(), R.string.pref_installation_method_aurora_unavailable);
return false;
}
} else if (Aurora.INSTALLATION_METHOD_PRIVILEGED.equals(newValue)) {
if (!checkPrivileged()) {
return false;
}
@@ -68,6 +74,9 @@ class OnInstallationMethodChangeListener implements Preference.OnPreferenceChang
}
int summaryId;
switch (installationMethod) {
case Aurora.INSTALLATION_METHOD_AURORA:
summaryId = R.string.pref_installation_method_aurora;
break;
case Aurora.INSTALLATION_METHOD_PRIVILEGED:
summaryId = R.string.pref_installation_method_privileged;
break;
@@ -98,7 +107,7 @@ class OnInstallationMethodChangeListener implements Preference.OnPreferenceChang
@Override
protected void onPostExecute(Void aVoid) {
if (!available) {
Toast.makeText(fragment.getActivity().getApplicationContext(), R.string.pref_not_privileged, Toast.LENGTH_LONG).show();
ContextUtil.toast(fragment.getActivity(), R.string.pref_not_privileged);
return;
}
showPrivilegedInstallationDialog();

View File

@@ -55,11 +55,9 @@ public class ConvertToSystemTask extends SystemRemountTask {
private String getTargetPath() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return "/system/priv-app/" + app.getPackageName() + "/" + app.getPackageName() + ".apk";
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return "/system/priv-app/" + app.getPackageName() + ".apk";
return "/system/priv-app/" + app.getPackageName() + File.separator + app.getPackageName() + ".apk";
} else {
return "/system/app/" + app.getPackageName() + ".apk";
return "/system/priv-app/" + app.getPackageName() + ".apk";
}
}
}

View File

@@ -94,20 +94,11 @@ public abstract class SystemRemountTask extends TaskWithProgress<List<String>> {
new AlertDialog.Builder(context)
.setMessage(R.string.dialog_message_reboot_required)
.setTitle(R.string.dialog_title_reboot_required)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new RebootTask().execute();
dialog.dismiss();
}
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
new RebootTask().execute();
dialog.dismiss();
})
.setNegativeButton(R.string.dialog_two_factor_cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show()
;
.setNegativeButton(R.string.dialog_two_factor_cancel, (dialog, which) -> dialog.dismiss())
.show();
}
}

View File

@@ -44,11 +44,13 @@
<item>DEFAULT</item>
<item>ROOT</item>
<item>PRIVILEGED</item>
<item>AURORA</item>
</string-array>
<string-array name="installationMethodLabels">
<item>@string/pref_installation_method_default</item>
<item>@string/pref_installation_method_root</item>
<item>@string/pref_installation_method_privileged</item>
<item>@string/pref_installation_method_aurora</item>
</string-array>
<string-array name="filterRatingValues" translatable="false">
<item>0</item>

View File

@@ -298,6 +298,8 @@
<string name="pref_installation_method">Installation method</string>
<string name="pref_installation_method_default">Default installation dialog, no background installs</string>
<string name="pref_installation_method_privileged">Using system permissions</string>
<string name="pref_installation_method_aurora">Using Aurora services</string>
<string name="pref_installation_method_aurora_unavailable">Aurora Services not installed</string>
<string name="pref_installation_method_root">Using root</string>
<string name="pref_message_fallback">Attempt to set a fallback directory (%1$s)?</string>
<string name="pref_not_privileged">Only available if Aurora is a system app</string>