1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.packageinstaller.common; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.os.SystemClock; 23 import android.util.Log; 24 25 import androidx.annotation.NonNull; 26 27 import java.io.File; 28 import java.io.IOException; 29 30 /** 31 * Manages files of the package installer and resets state during boot. 32 */ 33 public class TemporaryFileManager extends BroadcastReceiver { 34 private static final String LOG_TAG = TemporaryFileManager.class.getSimpleName(); 35 36 /** 37 * Create a new file to hold a staged file. 38 * 39 * @param context The context of the caller 40 * 41 * @return A new file 42 */ 43 @NonNull getStagedFile(@onNull Context context)44 public static File getStagedFile(@NonNull Context context) throws IOException { 45 return File.createTempFile("package", ".apk", context.getNoBackupFilesDir()); 46 } 47 48 /** 49 * Get the file used to store the results of installs. 50 * 51 * @param context The context of the caller 52 * 53 * @return the file used to store the results of installs 54 */ 55 @NonNull getInstallStateFile(@onNull Context context)56 public static File getInstallStateFile(@NonNull Context context) { 57 return new File(context.getNoBackupFilesDir(), "install_results.xml"); 58 } 59 60 /** 61 * Get the file used to store the results of uninstalls. 62 * 63 * @param context The context of the caller 64 * 65 * @return the file used to store the results of uninstalls 66 */ 67 @NonNull getUninstallStateFile(@onNull Context context)68 public static File getUninstallStateFile(@NonNull Context context) { 69 return new File(context.getNoBackupFilesDir(), "uninstall_results.xml"); 70 } 71 72 @Override onReceive(Context context, Intent intent)73 public void onReceive(Context context, Intent intent) { 74 long systemBootTime = System.currentTimeMillis() - SystemClock.elapsedRealtime(); 75 76 File[] filesOnBoot = context.getNoBackupFilesDir().listFiles(); 77 78 if (filesOnBoot == null) { 79 return; 80 } 81 82 for (int i = 0; i < filesOnBoot.length; i++) { 83 File fileOnBoot = filesOnBoot[i]; 84 85 if (systemBootTime > fileOnBoot.lastModified()) { 86 boolean wasDeleted = fileOnBoot.delete(); 87 if (!wasDeleted) { 88 Log.w(LOG_TAG, "Could not delete " + fileOnBoot.getName() + " onBoot"); 89 } 90 } else { 91 Log.w(LOG_TAG, fileOnBoot.getName() + " was created before onBoot broadcast was " 92 + "received"); 93 } 94 } 95 } 96 } 97