pt 1 in reviving the android build (copied from pm 28a1, wish me luck)

This commit is contained in:
wuggy 2026-04-08 15:43:25 -07:00
commit d7788a6d6d
4249 changed files with 468189 additions and 0 deletions

View file

@ -0,0 +1,81 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mozilla.gecko.cleanup;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.annotation.VisibleForTesting;
import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
/**
* Encapsulates the code to run the {@link FileCleanupService}. Call
* {@link #startIfReady(Context, SharedPreferences, String)} to start the clean-up.
*
* Note: for simplicity, the current implementation does not cache which
* files have been cleaned up and will attempt to delete the same files
* each time it is run. If the file deletion list grows large, consider
* keeping a cache.
*/
public class FileCleanupController {
private static final long MILLIS_BETWEEN_CLEANUPS = TimeUnit.DAYS.toMillis(7);
@VisibleForTesting static final String PREF_LAST_CLEANUP_MILLIS = "cleanup.lastFileCleanupMillis";
// These will be prepended with the path of the profile we're cleaning up.
private static final String[] PROFILE_FILES_TO_CLEANUP = new String[] {
"health.db",
"health.db-journal",
"health.db-shm",
"health.db-wal",
};
/**
* Starts the clean-up if it's time to clean-up, otherwise returns. For simplicity,
* it does not schedule the cleanup for some point in the future - this method will
* have to be called again (i.e. polled) in order to run the clean-up service.
*
* @param context Context of the calling {@link android.app.Activity}
* @param sharedPrefs The {@link SharedPreferences} instance to store the controller state to
* @param profilePath The path to the profile the service should clean-up files from
*/
public static void startIfReady(final Context context, final SharedPreferences sharedPrefs, final String profilePath) {
if (!isCleanupReady(sharedPrefs)) {
return;
}
recordCleanupScheduled(sharedPrefs);
final Intent fileCleanupIntent = new Intent(context, FileCleanupService.class);
fileCleanupIntent.setAction(FileCleanupService.ACTION_DELETE_FILES);
fileCleanupIntent.putExtra(FileCleanupService.EXTRA_FILE_PATHS_TO_DELETE, getFilesToCleanup(profilePath + "/"));
context.startService(fileCleanupIntent);
}
private static boolean isCleanupReady(final SharedPreferences sharedPrefs) {
final long lastCleanupMillis = sharedPrefs.getLong(PREF_LAST_CLEANUP_MILLIS, -1);
return lastCleanupMillis + MILLIS_BETWEEN_CLEANUPS < System.currentTimeMillis();
}
private static void recordCleanupScheduled(final SharedPreferences sharedPrefs) {
final SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putLong(PREF_LAST_CLEANUP_MILLIS, System.currentTimeMillis()).apply();
}
@VisibleForTesting
static ArrayList<String> getFilesToCleanup(final String profilePath) {
final ArrayList<String> out = new ArrayList<>(PROFILE_FILES_TO_CLEANUP.length);
for (final String path : PROFILE_FILES_TO_CLEANUP) {
// Append a file separator, just in-case the caller didn't include one.
out.add(profilePath + File.separator + path);
}
return out;
}
}

View file

@ -0,0 +1,80 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mozilla.gecko.cleanup;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import java.io.File;
import java.util.ArrayList;
/**
* An IntentService to delete files.
*
* It takes an {@link ArrayList} of String file paths to delete via the extra
* {@link #EXTRA_FILE_PATHS_TO_DELETE}. If these file paths are directories, they will
* not be traversed recursively and will only be deleted if empty. This is to avoid accidentally
* trashing a users' profile if a folder is accidentally listed.
*
* An IntentService was chosen because:
* * It generally won't be killed when the Activity is
* * (unlike HandlerThread) The system handles scheduling, prioritizing,
* and shutting down the underlying background thread
* * (unlike an existing background thread) We don't block our background operations
* for this, which doesn't directly affect the user.
*
* The major trade-off is that this Service is very dangerous if it's exported... so don't do that!
*/
public class FileCleanupService extends IntentService {
private static final String LOGTAG = "Gecko" + FileCleanupService.class.getSimpleName();
private static final String WORKER_THREAD_NAME = LOGTAG + "Worker";
public static final String ACTION_DELETE_FILES = "org.mozilla.gecko.intent.action.DELETE_FILES";
public static final String EXTRA_FILE_PATHS_TO_DELETE = "org.mozilla.gecko.file_paths_to_delete";
public FileCleanupService() {
super(WORKER_THREAD_NAME);
// We're likely to get scheduled again - let's wait until then in order to avoid:
// * The coding complexity of re-running this
// * Consuming system resources: we were probably killed for resource conservation purposes
setIntentRedelivery(false);
}
@Override
protected void onHandleIntent(final Intent intent) {
if (!isIntentValid(intent)) {
return;
}
final ArrayList<String> filesToDelete = intent.getStringArrayListExtra(EXTRA_FILE_PATHS_TO_DELETE);
for (final String path : filesToDelete) {
final File file = new File(path);
file.delete();
}
}
private static boolean isIntentValid(final Intent intent) {
if (intent == null) {
Log.w(LOGTAG, "Received null intent");
return false;
}
if (!intent.getAction().equals(ACTION_DELETE_FILES)) {
Log.w(LOGTAG, "Received unknown intent action: " + intent.getAction());
return false;
}
if (!intent.hasExtra(EXTRA_FILE_PATHS_TO_DELETE)) {
Log.w(LOGTAG, "Received intent with no files extra");
return false;
}
return true;
}
}