@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
// 处理 name 为 null 的情况
// At least one application in the world actually passes in a null
// name. This happened to work because when we generated the file name
// we would stringify it to "null.xml". Nice.
if (mPackageInfo.getApplicationInfo().targetSdkVersion <
Build.VERSION_CODES.KITKAT) {
if (name == null) {
name = "null";
}
}
File file;
synchronized (ContextImpl.class) {
if (mSharedPrefsPaths == null) {
//创建缓存的 map
mSharedPrefsPaths = new ArrayMap<>();
}
//先从缓存中获取 File
file = mSharedPrefsPaths.get(name);
if (file == null) {
//缓存中没有,先生成file
file = getSharedPreferencesPath(name);
//加入缓存
mSharedPrefsPaths.put(name, file);
}
}
//通过文件生成 SharedPreferences
return getSharedPreferences(file, mode);
}
Internal utility class to keep track of process-global work that's outstanding and hasn't been finished yet.
New work will be {@link #queue queued}. It is possible to add 'finisher'-runnables that are {@link #waitToFinish guaranteed to be run}. This is used to make sure the work has been finished.
This was created for writing SharedPreference edits out asynchronously so we'd have a mechanism to wait for the writes in Activity.onPause and similar places, but we may use this mechanism for other things in the future.
The queued asynchronous work is performed on a separate, dedicated thread.
private static File ensurePrivateDirExists(File file) {
return ensurePrivateDirExists(file, 0771, -1, null);
}
private static File ensurePrivateDirExists(File file, int mode, int gid, String xattr) {
if (!file.exists()) {
final String path = file.getAbsolutePath();
try {
Os.mkdir(path, mode);
Os.chmod(path, mode);
if (gid != -1) {
Os.chown(path, -1, gid);
}
} catch (ErrnoException e) {
if (e.errno == OsConstants.EEXIST) {
// We must have raced with someone; that's okay
} else {
Log.w(TAG, "Failed to ensure " + file + ": " + e.getMessage());
}
}
if (xattr != null) {
try {
final StructStat stat = Os.stat(file.getAbsolutePath());
final byte[] value = new byte[8];
Memory.pokeLong(value, 0, stat.st_ino, ByteOrder.nativeOrder());
Os.setxattr(file.getParentFile().getAbsolutePath(), xattr, value, 0);
} catch (ErrnoException e) {
Log.w(TAG, "Failed to update " + xattr + ": " + e.getMessage());
}
}
}
return file;
}
private File makeFilename(File base, String name) {
//文件名包含分隔符时抛出异常
if (name.indexOf(File.separatorChar) < 0) {
final File res = new File(base, name);
return res;
}
throw new IllegalArgumentException(
"File " + name + " contains a path separator");
}
@Override
public SharedPreferences getSharedPreferences(File file, int mode) {
SharedPreferencesImpl sp;
synchronized (ContextImpl.class) {
final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();
// 先从缓存中获取
sp = cache.get(file);
if (sp == null) {
//一些权限检查
checkMode(mode);
if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O) {
if (isCredentialProtectedStorage()
&& !getSystemService(UserManager.class)
.isUserUnlockingOrUnlocked(UserHandle.myUserId())) {
throw new IllegalStateException("SharedPreferences in credential encrypted "
+ "storage are not available until after user is unlocked");
}
}
//创建 SharedPreferences 实例
sp = new SharedPreferencesImpl(file, mode);
// 放入缓存
cache.put(file, sp);
return sp;
}
}
if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
// If somebody else (some other process) changed the prefs
// file behind our back, we reload it. This has been the
// historical (if undocumented) behavior.
sp.startReloadIfChangedUnexpectedly();
}
return sp;
}
private void checkMode(int mode) {
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.N) {
if ((mode & MODE_WORLD_READABLE) != 0) {
throw new SecurityException("MODE_WORLD_READABLE no longer supported");
}
if ((mode & MODE_WORLD_WRITEABLE) != 0) {
throw new SecurityException("MODE_WORLD_WRITEABLE no longer supported");
}
}
}
private void loadFromDisk() {
synchronized (mLock) {
//已经读取成功,直接返回
if (mLoaded) {
return;
}
//如果有备份文件,优先从备份文件恢复
if (mBackupFile.exists()) {
mFile.delete();
mBackupFile.renameTo(mFile);
}
}
Map<String, Object> map = null;
Throwable thrown = null;
try {
if (mFile.canRead()) {
BufferedInputStream str = null;
try {
//创建文件输入流
str = new BufferedInputStream(
new FileInputStream(mFile), 16 * 1024);
//将读取的文件解析成Map
map = (Map<String, Object>) XmlUtils.readMapXml(str);
} catch (Exception e) {
Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e);
} finally {
IoUtils.closeQuietly(str);
}
}
} catch (ErrnoException e) {
// An errno exception means the stat failed. Treat as empty/non-existing by
// ignoring.
} catch (Throwable t) {
thrown = t;
}
synchronized (mLock) {
//读取完成后设置读取状态为true
mLoaded = true;
mThrowable = thrown;
// It's important that we always signal waiters, even if we'll make
// them fail with an exception. The try-finally is pretty wide, but
// better safe than sorry.
try {
if (thrown == null) {
if (map != null) {
//将 mMap 赋值
mMap = map;
} else {
mMap = new HashMap<>();
}
}
// In case of a thrown exception, we retain the old map. That allows
// any open editors to commit and store updates.
} catch (Throwable t) {
mThrowable = t;
} finally {
//通知所有可能正在等待的线程
mLock.notifyAll();
}
}
}
public String getString(String key, @Nullable String defValue) {
synchronized (mLock) {
awaitLoadedLocked();
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
private final Object mLock = new Object();
private void awaitLoadedLocked() {
while (!mLoaded) {
try {
//没有读取成功,先等待
mLock.wait();
} catch (InterruptedException unused) {
}
}
if (mThrowable != null) {
throw new IllegalStateException(mThrowable);
}
}
@Override
public Editor edit() {
synchronized (mLock) {
awaitLoadedLocked();
}
return new EditorImpl();
}
public final class EditorImpl implements Editor {
//写锁
private final Object mEditorLock = new Object();
//新增或者发生变更的键值对
@GuardedBy("mEditorLock")
private final Map<String, Object> mModified = new HashMap<>();
//是否需要清空之前的值
@GuardedBy("mEditorLock")
private boolean mClear = false;
//....
}
private static Handler getHandler() {
synchronized (sLock) {
if (sHandler == null) {
//创建新的线程
HandlerThread handlerThread = new HandlerThread("queued-work-looper",
Process.THREAD_PRIORITY_FOREGROUND);
handlerThread.start();
sHandler = new QueuedWorkHandler(handlerThread.getLooper());
}
return sHandler;
}
}
private static class QueuedWorkHandler extends Handler {
static final int MSG_RUN = 1;
QueuedWorkHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
if (msg.what == MSG_RUN) {
processPendingWork();
}
}
}
private static void processPendingWork() {
synchronized (sProcessingWork) {
LinkedList<Runnable> work;
synchronized (sLock) {
work = (LinkedList<Runnable>) sWork.clone();
sWork.clear();
// 移除所有MSG_RUN消息
getHandler().removeMessages(QueuedWorkHandler.MSG_RUN);
}
if (work.size() > 0) {
//按顺序执行任务
for (Runnable w : work) {
w.run();
}
}
}
}
/**
* Trigger queued work to be processed immediately. The queued work is processed on a separate
* thread asynchronous. While doing that run and process all finishers on this thread. The
* finishers can be implemented in a way to check weather the queued work is finished.
*
* Is called from the Activity base class's onPause(), after BroadcastReceiver's onReceive,
* after Service command handling, etc. (so async work is never lost)
*/
public static void waitToFinish() {
Handler handler = getHandler();
synchronized (sLock) {
if (handler.hasMessages(QueuedWorkHandler.MSG_RUN)) {
// Delayed work will be processed at processPendingWork() below
handler.removeMessages(QueuedWorkHandler.MSG_RUN);
}
// We should not delay any work as this might delay the finishers
sCanDelay = false;
}
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
try {
processPendingWork();
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
try {
while (true) {
Runnable finisher;
synchronized (sLock) {
finisher = sFinishers.poll();
}
if (finisher == null) {
break;
}
finisher.run();
}
} finally {
sCanDelay = true;
}
//...
}
//Service 启动
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess();
}
int res;
if (!data.taskRemoved) {
//调用Service的 onStartCommand
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
//.....
}
}
}
//service stop
private void handleStopService(IBinder token) {
Service s = mServices.remove(token);
if (s != null) {
try {
//调用Service的onDestroy方法
s.onDestroy();
s.detachAndCleanUp();
//.....
QueuedWork.waitToFinish();
//....
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to stop service " + s
+ ": " + e.toString(), e);
}
Slog.i(TAG, "handleStopService: exception for " + token, e);
}
}
}
//在 Android 11 之前,在 onPause调用后执行 QueuedWork.waitToFinish();
@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, PendingTransactionActions pendingActions, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(r, finished, reason, pendingActions);
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
mSomeActivitiesChanged = true;
}
}
//在Android 11之后,在onStop 后调用
public void handleStopActivity(IBinder token, boolean show, int configChanges,
PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {
final ActivityClientRecord r = mActivities.get(token);
r.activity.mConfigChangeFlags |= configChanges;
final StopInfo stopInfo = new StopInfo();
performStopActivityInner(r, stopInfo, show, true /* saveState */, finalStateRequest,
reason);
//...
// Make sure any pending writes are now committed.
if (!r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
//...
}