Merge "Context.getSystemService() shouldn't return null..." into rvc-dev
This commit is contained in:
@@ -1658,6 +1658,9 @@ public final class SystemServiceRegistry {
|
|||||||
public final T getService(ContextImpl ctx) {
|
public final T getService(ContextImpl ctx) {
|
||||||
final Object[] cache = ctx.mServiceCache;
|
final Object[] cache = ctx.mServiceCache;
|
||||||
final int[] gates = ctx.mServiceInitializationStateArray;
|
final int[] gates = ctx.mServiceInitializationStateArray;
|
||||||
|
boolean interrupted = false;
|
||||||
|
|
||||||
|
T ret = null;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
boolean doInitialize = false;
|
boolean doInitialize = false;
|
||||||
@@ -1665,7 +1668,8 @@ public final class SystemServiceRegistry {
|
|||||||
// Return it if we already have a cached instance.
|
// Return it if we already have a cached instance.
|
||||||
T service = (T) cache[mCacheIndex];
|
T service = (T) cache[mCacheIndex];
|
||||||
if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
|
if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
|
||||||
return service;
|
ret = service;
|
||||||
|
break; // exit the for (;;)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, there's no cached instance.
|
// If we get here, there's no cached instance.
|
||||||
@@ -1708,24 +1712,33 @@ public final class SystemServiceRegistry {
|
|||||||
cache.notifyAll();
|
cache.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return service;
|
ret = service;
|
||||||
|
break; // exit the for (;;)
|
||||||
}
|
}
|
||||||
// The other threads will wait for the first thread to call notifyAll(),
|
// The other threads will wait for the first thread to call notifyAll(),
|
||||||
// and go back to the top and retry.
|
// and go back to the top and retry.
|
||||||
synchronized (cache) {
|
synchronized (cache) {
|
||||||
|
// Repeat until the state becomes STATE_READY or STATE_NOT_FOUND.
|
||||||
|
// We can't respond to interrupts here; just like we can't in the "doInitialize"
|
||||||
|
// path, so we remember the interrupt state here and re-interrupt later.
|
||||||
while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
|
while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
|
||||||
try {
|
try {
|
||||||
|
// Clear the interrupt state.
|
||||||
|
interrupted |= Thread.interrupted();
|
||||||
cache.wait();
|
cache.wait();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// This shouldn't normally happen, but if someone interrupts the
|
// This shouldn't normally happen, but if someone interrupts the
|
||||||
// thread, it will.
|
// thread, it will.
|
||||||
Slog.wtf(TAG, "getService() interrupted");
|
Slog.w(TAG, "getService() interrupted");
|
||||||
Thread.currentThread().interrupt();
|
interrupted = true;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (interrupted) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
|
public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
|
||||||
|
|||||||
Reference in New Issue
Block a user