Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.
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
27 changes: 13 additions & 14 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
compileSdkVersion 27

defaultConfig {
applicationId "de.robv.android.xposed.installer"
minSdkVersion 15
targetSdkVersion 25
versionCode 40
versionName "3.1.2"
versionCode 43
versionName "3.1.5"
archivesBaseName = "XposedInstaller_${versionName}".replace(' ', '_')
}

Expand All @@ -25,14 +24,14 @@ android {
}

dependencies {
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:customtabs:25.3.1'
compile 'com.android.support:support-v13:25.3.1'
compile 'com.afollestad.material-dialogs:commons:0.9.0.2'
compile 'se.emilsjolander:stickylistheaders:2.7.0'
compile 'eu.chainfire:libsuperuser:1.0.0.201608240809'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'de.psdev.licensesdialog:licensesdialog:1.8.1'
compile fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:cardview-v7:27.0.2'
implementation 'com.android.support:design:27.0.2'
implementation 'com.android.support:customtabs:27.0.2'
implementation 'com.android.support:support-v13:27.0.2'
implementation 'com.afollestad.material-dialogs:commons:0.9.0.2'
implementation 'se.emilsjolander:stickylistheaders:2.7.0'
implementation 'eu.chainfire:libsuperuser:1.0.0.201608240809'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'de.psdev.licensesdialog:licensesdialog:1.8.1'
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
Expand Down Expand Up @@ -93,6 +94,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
mModuleUtil.addListener(this);

mListView = (StickyListHeadersListView) v.findViewById(R.id.listModules);
if (Build.VERSION.SDK_INT >= 26) {
mListView.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
}
mListView.setAdapter(mAdapter);
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import android.support.annotation.NonNull;
import android.support.v13.app.FragmentCompat;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
Expand Down Expand Up @@ -175,9 +176,11 @@ private void clear() {
}

private void send() {
Uri uri = FileProvider.getUriForFile(getActivity(), "de.robv.android.xposed.installer.fileprovider", mFileErrorLog);
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(save()));
sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
sendIntent.setType("application/html");
startActivity(Intent.createChooser(sendIntent, getResources().getString(R.string.menuSend)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.graphics.Color;
Expand Down Expand Up @@ -32,6 +33,7 @@

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Set;

import de.robv.android.xposed.installer.R;
Expand Down Expand Up @@ -110,6 +112,8 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
manufacturer.setText(getUIFramework());
cpu.setText(FrameworkZips.ARCH);

determineVerifiedBootState(v);

// Known issues
refreshKnownIssue(v);

Expand Down Expand Up @@ -190,6 +194,9 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_installer, menu);
menu.findItem(R.id.show_outdated).setChecked(mShowOutdated);
if (Build.VERSION.SDK_INT < 26) {
menu.findItem(R.id.dexopt_now).setVisible(false);
}
}

@Override
Expand All @@ -207,6 +214,40 @@ public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which)
});
return true;

case R.id.dexopt_now:
new MaterialDialog.Builder(getActivity())
.title(R.string.dexopt_now)
.content(R.string.this_may_take_a_while)
.progress(true, 0)
.cancelable(false)
.showListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(final DialogInterface dialog) {
new Thread("dexopt") {
@Override
public void run() {
RootUtil rootUtil = new RootUtil();
if (!rootUtil.startShell()) {
dialog.dismiss();
NavUtil.showMessage(getActivity(), getString(R.string.root_failed));
return;
}

rootUtil.execute("cmd package bg-dexopt-job", null);

dialog.dismiss();
XposedApp.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getActivity(), R.string.done, Toast.LENGTH_LONG).show();
}
});
}
}.start();
}
}).show();
return true;

case R.id.show_outdated:
mShowOutdated = !item.isChecked();
XposedApp.getPreferences().edit().putBoolean("framework_download_show_outdated", mShowOutdated).apply();
Expand All @@ -227,15 +268,36 @@ private void confirmReboot(int contentTextId, MaterialDialog.SingleButtonCallbac
.show();
}

private File getCanonicalFile(File file) {
try {
return file.getCanonicalFile();
} catch (IOException e) {
Log.e(XposedApp.TAG, "Failed to get canonical file for " + file.getAbsolutePath(), e);
return file;
}
}

private String getPathWithCanonicalPath(File file, File canonical) {
if (file.equals(canonical)) {
return file.getAbsolutePath();
} else {
return file.getAbsolutePath() + " \u2192 " + canonical.getAbsolutePath();
}
}

@SuppressLint("StringFormatInvalid")
private void refreshKnownIssue(View v) {
final String issueName;
final String issueLink;
final File baseDir = new File(XposedApp.BASE_DIR);
final ApplicationInfo appInfo = getActivity().getApplicationInfo();
final Set<String> missingFeatures = XposedApp.getXposedProp().getMissingInstallerFeatures();
final File baseDir = new File(XposedApp.BASE_DIR);
final File baseDirCanonical = getCanonicalFile(baseDir);
final File baseDirActual = new File(Build.VERSION.SDK_INT >= 24 ? appInfo.deviceProtectedDataDir : appInfo.dataDir);
final File baseDirActualCanonical = getCanonicalFile(baseDirActual);
final InstallZipUtil.XposedProp prop = XposedApp.getXposedProp();
final Set<String> missingFeatures = prop != null ? prop.getMissingInstallerFeatures() : null;

if (!missingFeatures.isEmpty()) {
if (missingFeatures != null && !missingFeatures.isEmpty()) {
InstallZipUtil.reportMissingFeatures(missingFeatures);
issueName = getString(R.string.installer_needs_update, getString(R.string.app_name));
issueLink = getString(R.string.about_support);
Expand All @@ -248,15 +310,10 @@ private void refreshKnownIssue(View v) {
} else if (Build.VERSION.SDK_INT < 24 && new File("/system/framework/twframework.jar").exists()) {
issueName = "Samsung TouchWiz ROM";
issueLink = "https://forum.xda-developers.com/showthread.php?t=3034811";
} else if (Build.VERSION.SDK_INT < 24 && !baseDir.equals(new File(appInfo.dataDir))) {
Log.e(XposedApp.TAG, "Base directory: " + appInfo.dataDir);
Log.e(XposedApp.TAG, "Expected: " + XposedApp.BASE_DIR);
issueName = getString(R.string.known_issue_wrong_base_directory);
issueLink = "https://github.com/rovo89/XposedInstaller/issues/395";
} else if (Build.VERSION.SDK_INT >= 24 && !baseDir.equals(new File(appInfo.deviceProtectedDataDir))) {
Log.e(XposedApp.TAG, "Base directory: " + appInfo.deviceProtectedDataDir);
Log.e(XposedApp.TAG, "Expected: " + XposedApp.BASE_DIR);
issueName = getString(R.string.known_issue_wrong_base_directory);
} else if (!baseDirCanonical.equals(baseDirActualCanonical)) {
Log.e(XposedApp.TAG, "Base directory: " + getPathWithCanonicalPath(baseDir, baseDirCanonical));
Log.e(XposedApp.TAG, "Expected: " + getPathWithCanonicalPath(baseDirActual, baseDirActualCanonical));
issueName = getString(R.string.known_issue_wrong_base_directory, getPathWithCanonicalPath(baseDirActual, baseDirActualCanonical));
issueLink = "https://github.com/rovo89/XposedInstaller/issues/395";
} else if (!baseDir.exists()) {
issueName = getString(R.string.known_issue_missing_base_directory);
Expand Down Expand Up @@ -321,6 +378,34 @@ private String getUIFramework() {
return manufacturer;
}

private void determineVerifiedBootState(View v) {
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method m = c.getDeclaredMethod("get", String.class, String.class);
m.setAccessible(true);

String propSystemVerified = (String) m.invoke(null, "partition.system.verified", "0");
String propState = (String) m.invoke(null, "ro.boot.verifiedbootstate", "");
File fileDmVerityModule = new File("/sys/module/dm_verity");

boolean verified = !propSystemVerified.equals("0");
boolean detected = !propState.isEmpty() || fileDmVerityModule.exists();

TextView tv = v.findViewById(R.id.dmverity);
if (verified) {
tv.setText(R.string.verified_boot_active);
tv.setTextColor(getResources().getColor(R.color.warning));
} else if (detected) {
tv.setText(R.string.verified_boot_deactivated);
v.findViewById(R.id.dmverity_explanation).setVisibility(View.GONE);
} else {
v.findViewById(R.id.dmverity_row).setVisibility(View.GONE);
}
} catch (Exception e) {
Log.e(XposedApp.TAG, "Could not detect Verified Boot state", e);
}
}

@UiThread
private void refreshZipViews(View view) {
LinearLayout zips = (LinearLayout) view.findViewById(R.id.zips);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
import android.support.v4.content.ContextCompat;
Expand Down Expand Up @@ -468,10 +469,23 @@ private static String getFilenameFromUri(String uriString) {
return null;
}
Uri uri = Uri.parse(uriString);
if (!uri.getScheme().equals("file")) {
throw new UnsupportedOperationException("Not a file URI: " + uriString);
if (uri.getScheme().equals("file")) {
return uri.getPath();
} else if (uri.getScheme().equals("content")) {
Context context = XposedApp.getInstance();
Cursor c = null;
try {
c = context.getContentResolver().query(uri, new String[]{MediaStore.Files.FileColumns.DATA}, null, null, null);
c.moveToFirst();
return c.getString(c.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA));
} finally {
if (c != null) {
c.close();
}
}
} else {
throw new UnsupportedOperationException("Unexpected URI: " + uriString);
}
return uri.getPath();
}

public static SyncDownloadInfo downloadSynchronously(String url, File target) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.content.Intent;
import android.net.Uri;
import android.provider.Browser;
import android.support.annotation.AnyThread;
import android.support.annotation.NonNull;
import android.support.customtabs.CustomTabsIntent;
import android.text.Spannable;
Expand Down Expand Up @@ -47,10 +48,16 @@ public static void startURL(Activity activity, String url) {
startURL(activity, parseURL(url));
}

public static void showMessage(@NonNull Context context, CharSequence message) {
new MaterialDialog.Builder(context)
.content(message)
.positiveText(android.R.string.ok)
.show();
@AnyThread
public static void showMessage(final @NonNull Context context, final CharSequence message) {
XposedApp.runOnUiThread(new Runnable() {
@Override
public void run() {
new MaterialDialog.Builder(context)
.content(message)
.positiveText(android.R.string.ok)
.show();
}
});
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_flash.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M7,2v11h3v9l7,-12h-4l4,-8z"/>
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_verified.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#757575"
android:pathData="M12,1L3,5v6c0,5.55 3.84,10.74 9,12 5.16,-1.26 9,-6.45 9,-12L21,5l-9,-4zM10,17l-4,-4 1.41,-1.41L10,14.17l6.59,-6.59L18,9l-8,8z"/>
</vector>
43 changes: 43 additions & 0 deletions app/src/main/res/layout/status_installer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,49 @@

</LinearLayout>

<LinearLayout
android:id="@+id/dmverity_row"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp">

<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_verified"/>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="32dp"
android:layout_marginStart="32dp"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingTop="8dp">

<TextView
android:id="@+id/dmverity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
tools:text="@string/verified_boot_deactivated"/>

<TextView
android:id="@+id/dmverity_explanation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/verified_boot_explanation"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

</LinearLayout>

</LinearLayout>

</LinearLayout>

</android.support.v7.widget.CardView>
Expand Down
Loading