Skip to content

Commit 7a56d7f

Browse files
committed
[Settings] Add user control for some installer options
- Request update ownership - Default package source - Set package origin and/or URI Signed-off-by: Muntashir Al-Islam <muntashirakon@riseup.net>
1 parent 3a4e6b2 commit 7a56d7f

7 files changed

Lines changed: 149 additions & 46 deletions

File tree

app/src/main/java/io/github/muntashirakon/AppManager/apk/installer/InstallerOptions.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public static InstallerOptions getDefault() {
3939
private String mOriginatingPackage;
4040
@Nullable
4141
private Uri mOriginatingUri;
42+
private boolean mSetOriginatingPackage;
4243
private int mPackageSource;
4344
private int mInstallScenario;
4445
private boolean mRequestUpdateOwnership;
@@ -50,8 +51,9 @@ private InstallerOptions() {
5051
mUserId = UserHandleHidden.myUserId();
5152
mInstallLocation = Prefs.Installer.getInstallLocation();
5253
mInstallerName = Prefs.Installer.getInstallerPackageName();
53-
mOriginatingPackage = Prefs.Installer.getOriginatingPackage();
54+
mOriginatingPackage = null;
5455
mOriginatingUri = null;
56+
mSetOriginatingPackage = Prefs.Installer.isSetOriginatingPackage();
5557
mPackageSource = Prefs.Installer.getPackageSource();
5658
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
5759
// If the user is always installing apps in the background, we expect that the user does
@@ -72,12 +74,13 @@ protected InstallerOptions(@NonNull Parcel in) {
7274
mInstallerName = in.readString();
7375
mOriginatingPackage = in.readString();
7476
mOriginatingUri = ParcelCompat.readParcelable(in, Uri.class.getClassLoader(), Uri.class);
77+
mSetOriginatingPackage = ParcelCompat.readBoolean(in);
7578
mPackageSource = in.readInt();
7679
mInstallScenario = in.readInt();
77-
mRequestUpdateOwnership = in.readByte() != 0;
78-
mSignApkFiles = in.readByte() != 0;
79-
mForceDexOpt = in.readByte() != 0;
80-
mBlockTrackers = in.readByte() != 0;
80+
mRequestUpdateOwnership = ParcelCompat.readBoolean(in);
81+
mSignApkFiles = ParcelCompat.readBoolean(in);
82+
mForceDexOpt = ParcelCompat.readBoolean(in);
83+
mBlockTrackers = ParcelCompat.readBoolean(in);
8184
}
8285

8386
public void copy(@NonNull InstallerOptions options) {
@@ -86,6 +89,7 @@ public void copy(@NonNull InstallerOptions options) {
8689
mInstallerName = options.mInstallerName;
8790
mOriginatingPackage = options.mOriginatingPackage;
8891
mOriginatingUri = options.mOriginatingUri;
92+
mSetOriginatingPackage = options.mSetOriginatingPackage;
8993
mPackageSource = options.mPackageSource;
9094
mInstallScenario = options.mInstallScenario;
9195
mRequestUpdateOwnership = options.mRequestUpdateOwnership;
@@ -101,12 +105,13 @@ public void writeToParcel(@NonNull Parcel dest, int flags) {
101105
dest.writeString(mInstallerName);
102106
dest.writeString(mOriginatingPackage);
103107
dest.writeParcelable(mOriginatingUri, flags);
108+
ParcelCompat.writeBoolean(dest, mSetOriginatingPackage);
104109
dest.writeInt(mPackageSource);
105110
dest.writeInt(mInstallScenario);
106-
dest.writeByte((byte) (mRequestUpdateOwnership ? 1 : 0));
107-
dest.writeByte((byte) (mSignApkFiles ? 1 : 0));
108-
dest.writeByte((byte) (mForceDexOpt ? 1 : 0));
109-
dest.writeByte((byte) (mBlockTrackers ? 1 : 0));
111+
ParcelCompat.writeBoolean(dest, mRequestUpdateOwnership);
112+
ParcelCompat.writeBoolean(dest, mSignApkFiles);
113+
ParcelCompat.writeBoolean(dest, mForceDexOpt);
114+
ParcelCompat.writeBoolean(dest, mBlockTrackers);
110115
}
111116

112117
protected InstallerOptions(@NonNull JSONObject jsonObject) throws JSONException {
@@ -116,6 +121,7 @@ protected InstallerOptions(@NonNull JSONObject jsonObject) throws JSONException
116121
mOriginatingPackage = JSONUtils.optString(jsonObject, "originating_package");
117122
String originatingUri = JSONUtils.optString(jsonObject, "originating_uri", null);
118123
mOriginatingUri = originatingUri != null ? Uri.parse(originatingUri) : null;
124+
mSetOriginatingPackage = jsonObject.optBoolean("set_originating_package", Prefs.Installer.isSetOriginatingPackage());
119125
mPackageSource = jsonObject.getInt("package_source");
120126
mInstallScenario = jsonObject.getInt("install_scenario");
121127
mRequestUpdateOwnership = jsonObject.getBoolean("request_update_ownership");
@@ -133,6 +139,7 @@ public JSONObject serializeToJson() throws JSONException {
133139
jsonObject.put("installer_name", mInstallerName);
134140
jsonObject.put("originating_package", mOriginatingPackage);
135141
jsonObject.put("originating_uri", mOriginatingUri != null ? mOriginatingUri.toString() : null);
142+
jsonObject.put("set_originating_package", mSetOriginatingPackage);
136143
jsonObject.put("package_source", mPackageSource);
137144
jsonObject.put("install_scenario", mInstallScenario);
138145
jsonObject.put("request_update_ownership", mRequestUpdateOwnership);
@@ -206,6 +213,14 @@ public void setOriginatingUri(@Nullable Uri originatingUri) {
206213
mOriginatingUri = originatingUri;
207214
}
208215

216+
public boolean isSetOriginatingPackage() {
217+
return mSetOriginatingPackage;
218+
}
219+
220+
public void setSetOriginatingPackage(boolean setOriginatingPackage) {
221+
mSetOriginatingPackage = setOriginatingPackage;
222+
}
223+
209224
public int getPackageSource() {
210225
return mPackageSource;
211226
}

app/src/main/java/io/github/muntashirakon/AppManager/apk/installer/PackageInstallerCompat.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -635,11 +635,13 @@ public boolean install(@NonNull ApkFile apkFile, @NonNull List<String> selectedS
635635
}
636636
});
637637
userId = allRequestedUsers[0];
638+
String originatingPackage = options.isSetOriginatingPackage() ? options.getOriginatingPackage() : null;
639+
Uri originatingUri = options.isSetOriginatingPackage() ? options.getOriginatingUri() : null;
638640
Log.d(TAG, "Install: opening session...");
639641
if (!openSession(userId, installFlags, options.getInstallerName(),
640-
options.getInstallLocation(), options.getOriginatingPackage(),
641-
options.getOriginatingUri(), options.getInstallScenario(),
642-
options.getPackageSource(), options.requestUpdateOwnership())) {
642+
options.getInstallLocation(), originatingPackage, originatingUri,
643+
options.getInstallScenario(), options.getPackageSource(),
644+
options.requestUpdateOwnership())) {
643645
return false;
644646
}
645647
List<ApkFile.Entry> selectedEntries = new ArrayList<>();
@@ -711,10 +713,12 @@ public boolean install(@NonNull Path[] apkFiles, @NonNull String packageName, @N
711713
}
712714
}
713715
userId = allRequestedUsers[0];
716+
String originatingPackage = options.isSetOriginatingPackage() ? options.getOriginatingPackage() : null;
717+
Uri originatingUri = options.isSetOriginatingPackage() ? options.getOriginatingUri() : null;
714718
if (!openSession(userId, installFlags, options.getInstallerName(),
715-
options.getInstallLocation(), options.getOriginatingPackage(),
716-
options.getOriginatingUri(), options.getInstallScenario(),
717-
options.getPackageSource(), options.requestUpdateOwnership())) {
719+
options.getInstallLocation(), originatingPackage, originatingUri,
720+
options.getInstallScenario(), options.getPackageSource(),
721+
options.requestUpdateOwnership())) {
718722
return false;
719723
}
720724
long totalSize = 0;

app/src/main/java/io/github/muntashirakon/AppManager/settings/InstallerPreferences.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import static io.github.muntashirakon.AppManager.utils.UIUtils.getSmallerText;
77

88
import android.Manifest;
9+
import android.annotation.SuppressLint;
910
import android.content.Intent;
1011
import android.content.pm.PackageInfo;
12+
import android.content.pm.PackageInstaller;
1113
import android.content.pm.PackageManager;
1214
import android.net.Uri;
1315
import android.os.Build;
@@ -57,6 +59,23 @@ public class InstallerPreferences extends PreferenceFragment {
5759
R.string.install_location_prefer_external, // PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL
5860
};
5961

62+
@SuppressLint("InlinedApi")
63+
public static final Integer[] PKG_SOURCES = new Integer[] {
64+
PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED,
65+
PackageInstaller.PACKAGE_SOURCE_OTHER,
66+
PackageInstaller.PACKAGE_SOURCE_STORE,
67+
PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE,
68+
PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE,
69+
};
70+
71+
public static final int[] PKG_SOURCES_NAMES = new int[]{
72+
R.string._undefined, // PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED
73+
R.string.package_source_other, // PackageInstaller.PACKAGE_SOURCE_OTHER
74+
R.string.package_source_store, // PackageInstaller.PACKAGE_SOURCE_STORE
75+
R.string.package_source_local_file, // PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE
76+
R.string.package_source_downloaded_file, // PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE
77+
};
78+
6079
private SettingsActivity mActivity;
6180
private PackageManager mPm;
6281
private String mInstallerApp;
@@ -138,6 +157,34 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
138157
.show();
139158
return true;
140159
});
160+
// Update ownership
161+
SwitchPreferenceCompat updateOwnership = Objects.requireNonNull(findPreference("installer_update_ownership"));
162+
updateOwnership.setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
163+
updateOwnership.setChecked(Prefs.Installer.requestUpdateOwnership());
164+
// Package source
165+
Preference pkgSource = Objects.requireNonNull(findPreference("installer_default_pkg_source"));
166+
pkgSource.setSummary(PKG_SOURCES_NAMES[Prefs.Installer.getPackageSource()]);
167+
pkgSource.setOnPreferenceClickListener(preference -> {
168+
CharSequence[] pkgSourceTexts = new CharSequence[PKG_SOURCES_NAMES.length];
169+
for (int i = 0; i < PKG_SOURCES_NAMES.length; ++i) {
170+
pkgSourceTexts[i] = getString(PKG_SOURCES_NAMES[i]);
171+
}
172+
int defaultChoice = Prefs.Installer.getPackageSource();
173+
new SearchableSingleChoiceDialogBuilder<>(requireActivity(), PKG_SOURCES, pkgSourceTexts)
174+
.setTitle(R.string.pref_default_package_source)
175+
.setSelection(defaultChoice)
176+
.setPositiveButton(R.string.save, (dialog, which, newPkgSource) -> {
177+
Objects.requireNonNull(newPkgSource);
178+
Prefs.Installer.setPackageSource(newPkgSource);
179+
pkgSource.setSummary(PKG_SOURCES_NAMES[newPkgSource]);
180+
})
181+
.setNegativeButton(R.string.cancel, null)
182+
.show();
183+
return true;
184+
});
185+
// Set origin
186+
SwitchPreferenceCompat setOrigin = Objects.requireNonNull(findPreference("installer_set_origin"));
187+
setOrigin.setChecked(Prefs.Installer.isSetOriginatingPackage());
141188
// Sign apk before installing
142189
SwitchPreferenceCompat signApk = Objects.requireNonNull(findPreference("installer_sign_apk"));
143190
signApk.setChecked(Prefs.Installer.canSignApk());

app/src/main/java/io/github/muntashirakon/AppManager/settings/Prefs.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import android.content.ComponentName;
99
import android.content.ContentResolver;
1010
import android.content.Context;
11-
import android.content.pm.PackageInstaller;
1211
import android.content.pm.PackageManager;
1312
import android.net.Uri;
1413
import android.os.Build;
@@ -425,22 +424,21 @@ public static void setInstallerPackageName(@NonNull String packageName) {
425424
AppPref.set(AppPref.PrefKey.PREF_INSTALLER_INSTALLER_APP_STR, packageName);
426425
}
427426

428-
@Nullable
429-
public static String getOriginatingPackage() {
430-
return null;
427+
public static boolean isSetOriginatingPackage() {
428+
return AppPref.getBoolean(AppPref.PrefKey.PREF_INSTALLER_SET_ORIGIN_BOOL);
431429
}
432430

433431
public static int getPackageSource() {
434-
// Shell default
435-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
436-
return PackageInstaller.PACKAGE_SOURCE_OTHER;
437-
}
438-
return 0;
432+
return AppPref.getInt(AppPref.PrefKey.PREF_INSTALLER_DEFAULT_PKG_SOURCE_INT);
433+
}
434+
435+
public static void setPackageSource(int source) {
436+
AppPref.set(AppPref.PrefKey.PREF_INSTALLER_DEFAULT_PKG_SOURCE_INT, source);
439437
}
440438

441439
public static boolean requestUpdateOwnership() {
442-
// Shell default
443-
return false;
440+
// Shell default is false
441+
return AppPref.getBoolean(AppPref.PrefKey.PREF_INSTALLER_UPDATE_OWNERSHIP_BOOL);
444442
}
445443
}
446444

app/src/main/java/io/github/muntashirakon/AppManager/utils/AppPref.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import android.content.Context;
77
import android.content.SharedPreferences;
88
import android.content.pm.PackageInfo;
9+
import android.content.pm.PackageInstaller;
910
import android.net.Uri;
11+
import android.os.Build;
1012
import android.os.Environment;
1113
import android.util.Log;
1214
import android.view.View;
@@ -96,11 +98,14 @@ public enum PrefKey {
9698

9799
PREF_INSTALLER_BLOCK_TRACKERS_BOOL,
98100
PREF_INSTALLER_ALWAYS_ON_BACKGROUND_BOOL,
101+
PREF_INSTALLER_DEFAULT_PKG_SOURCE_INT,
99102
PREF_INSTALLER_DISPLAY_CHANGES_BOOL,
100103
PREF_INSTALLER_FORCE_DEX_OPT_BOOL,
101104
PREF_INSTALLER_INSTALL_LOCATION_INT,
102105
PREF_INSTALLER_INSTALLER_APP_STR,
106+
PREF_INSTALLER_SET_ORIGIN_BOOL,
103107
PREF_INSTALLER_SIGN_APK_BOOL,
108+
PREF_INSTALLER_UPDATE_OWNERSHIP_BOOL,
104109

105110
PREF_LAST_VERSION_CODE_LONG,
106111
PREF_LAYOUT_ORIENTATION_INT,
@@ -395,6 +400,8 @@ public Object getDefaultValue(@NonNull PrefKey key) {
395400
case PREF_LOG_VIEWER_SHOW_PID_TID_TIMESTAMP_BOOL:
396401
case PREF_LOG_VIEWER_OMIT_SENSITIVE_INFO_BOOL:
397402
case PREF_INSTALLER_DISPLAY_CHANGES_BOOL:
403+
case PREF_INSTALLER_SET_ORIGIN_BOOL:
404+
case PREF_INSTALLER_UPDATE_OWNERSHIP_BOOL:
398405
case PREF_VIRUS_TOTAL_PROMPT_BEFORE_UPLOADING_BOOL:
399406
case PREF_ZIP_ALIGN_BOOL:
400407
case PREF_SEND_NOTIFICATIONS_TO_CONNECTED_DEVICES_BOOL:
@@ -437,6 +444,11 @@ public Object getDefaultValue(@NonNull PrefKey key) {
437444
return "";
438445
case PREF_MODE_OF_OPS_STR:
439446
return Ops.MODE_AUTO;
447+
case PREF_INSTALLER_DEFAULT_PKG_SOURCE_INT:
448+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
449+
// Shell default
450+
return PackageInstaller.PACKAGE_SOURCE_OTHER;
451+
} else return 0;
440452
case PREF_INSTALLER_INSTALL_LOCATION_INT:
441453
return PackageInfo.INSTALL_LOCATION_AUTO;
442454
case PREF_INSTALLER_INSTALLER_APP_STR:

app/src/main/res/values/strings.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,4 +1524,13 @@
15241524
<string name="preview">Preview</string>
15251525
<string name="debloat_removal_unsafe">Unsafe</string>
15261526
<string name="sort_by_cpu_time">CPU time</string>
1527+
<string name="pref_request_update_ownership">Request \"update ownership\"</string>
1528+
<string name="pref_default_package_source">Default package source</string>
1529+
<string name="pref_set_origin">Set package origin and URI</string>
1530+
<string name="pref_request_update_ownership_description">Set the installer app as the \"update owner\" during the initial installation to prevent other installers from installing the app without user interaction.</string>
1531+
<string name="pref_set_origin_description">Record the origin or source of the app to be installed, reported by \"APK source\" in the App Info tab</string>
1532+
<string name="package_source_store">App store</string>
1533+
<string name="package_source_local_file">Local file</string>
1534+
<string name="package_source_downloaded_file">Downloaded file</string>
1535+
<string name="package_source_other">Other</string>
15271536
</resources>

0 commit comments

Comments
 (0)