-
Notifications
You must be signed in to change notification settings - Fork 282
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Installer] Fix installing background queued files
Android has a lifetime on the usage of content URIs. So, when the installer page is closed and the file descriptor is no longer held by the app, the URI becomes expired. As a result, the installer service can no longer access that URI and fails while processing the queue. This is fixed by caching the file itself so that the file exists even if the URI is expired. Signed-off-by: Muntashir Al-Islam <[email protected]>
- Loading branch information
1 parent
0a22039
commit 12c288a
Showing
17 changed files
with
401 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
app/src/main/java/io/github/muntashirakon/AppManager/apk/ApkSource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
package io.github.muntashirakon.AppManager.apk; | ||
|
||
import android.content.pm.ApplicationInfo; | ||
import android.net.Uri; | ||
import android.os.Parcelable; | ||
|
||
import androidx.annotation.AnyThread; | ||
import androidx.annotation.NonNull; | ||
import androidx.annotation.Nullable; | ||
|
||
public abstract class ApkSource implements Parcelable { | ||
@NonNull | ||
public static ApkSource getApkSource(@NonNull Uri uri, @Nullable String mimeType) { | ||
return new UriApkSource(uri, mimeType); | ||
} | ||
|
||
@NonNull | ||
public static ApkSource getCachedApkSource(@NonNull Uri uri, @Nullable String mimeType) { | ||
return new CachedApkSource(uri, mimeType); | ||
} | ||
|
||
@NonNull | ||
public static ApkSource getApkSource(@NonNull ApplicationInfo applicationInfo) { | ||
return new ApplicationInfoApkSource(applicationInfo); | ||
} | ||
|
||
@AnyThread | ||
@NonNull | ||
public abstract ApkFile resolve() throws ApkFile.ApkFileException; | ||
|
||
@AnyThread | ||
@NonNull | ||
public abstract ApkSource toCachedSource(); | ||
} |
72 changes: 72 additions & 0 deletions
72
app/src/main/java/io/github/muntashirakon/AppManager/apk/ApplicationInfoApkSource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
package io.github.muntashirakon.AppManager.apk; | ||
|
||
import android.content.pm.ApplicationInfo; | ||
import android.net.Uri; | ||
import android.os.Parcel; | ||
|
||
import androidx.annotation.NonNull; | ||
import androidx.core.os.ParcelCompat; | ||
|
||
import java.io.File; | ||
import java.util.Objects; | ||
|
||
public class ApplicationInfoApkSource extends ApkSource { | ||
@NonNull | ||
private final ApplicationInfo mApplicationInfo; | ||
|
||
private int mApkFileKey; | ||
|
||
ApplicationInfoApkSource(@NonNull ApplicationInfo applicationInfo) { | ||
mApplicationInfo = Objects.requireNonNull(applicationInfo); | ||
} | ||
|
||
@NonNull | ||
@Override | ||
public ApkFile resolve() throws ApkFile.ApkFileException { | ||
ApkFile apkFile = ApkFile.getInstance(mApkFileKey); | ||
if (apkFile != null && !apkFile.isClosed()) { | ||
// Usable past instance | ||
return apkFile; | ||
} | ||
mApkFileKey = ApkFile.createInstance(mApplicationInfo); | ||
return Objects.requireNonNull(ApkFile.getInstance(mApkFileKey)); | ||
} | ||
|
||
@NonNull | ||
@Override | ||
public ApkSource toCachedSource() { | ||
return new CachedApkSource(Uri.fromFile(new File(mApplicationInfo.publicSourceDir)), | ||
"application/vnd.android.package-archive"); | ||
} | ||
|
||
protected ApplicationInfoApkSource(@NonNull Parcel in) { | ||
mApplicationInfo = Objects.requireNonNull(ParcelCompat.readParcelable(in, | ||
ApplicationInfo.class.getClassLoader(), ApplicationInfo.class)); | ||
mApkFileKey = in.readInt(); | ||
} | ||
|
||
@Override | ||
public int describeContents() { | ||
return 0; | ||
} | ||
|
||
@Override | ||
public void writeToParcel(@NonNull Parcel dest, int flags) { | ||
dest.writeParcelable(mApplicationInfo, flags); | ||
dest.writeInt(mApkFileKey); | ||
} | ||
|
||
public static final Creator<ApplicationInfoApkSource> CREATOR = new Creator<ApplicationInfoApkSource>() { | ||
@Override | ||
public ApplicationInfoApkSource createFromParcel(Parcel source) { | ||
return new ApplicationInfoApkSource(source); | ||
} | ||
|
||
@Override | ||
public ApplicationInfoApkSource[] newArray(int size) { | ||
return new ApplicationInfoApkSource[size]; | ||
} | ||
}; | ||
} |
Oops, something went wrong.