以下是源码分析流程:
第一步:
frameworks/base/packages/systemUI/src/com/androID/systemUI/systemUIApplication.java
1.
public voID onCreate() {
super.onCreate();
Log.v(TAG, "systemUIApplication created.");
// This line is used to setup Dagger's dependency injection and should be kept at the
// top of this method.
TimingsTraceLog log = new TimingsTraceLog("systemUIBoottiming",
Trace.TRACE_TAG_APP);
log.traceBegin("DependencyInjection");
mContextAvailableCallback.onContextAvailable(this);
mRootComponent = systemUIFactory.getInstance().getRootComponent();
mComponentHelper = mRootComponent.getContextComponentHelper();
mBootCompleteCache = mRootComponent.provIDeBootCacheImpl();
log.traceEnd();
// Set the application theme that is inherited by all services. Note that setting the
// application theme in the manifest does only work for activitIEs. Keep this in sync with
// the theme set there.
settheme(R.style.theme_systemUI);
if (Process.myUserHandle().equals(UserHandle.SYstem)) {
IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
bootCompletedFilter.setPriority(IntentFilter.SYstem_HIGH_PRIORITY);
registerReceiver(new broadcastReceiver() {
@OverrIDe
public voID onReceive(Context context, Intent intent) {
if (mBootCompleteCache.isBootComplete()) return;
if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
unregisterReceiver(this);
mBootCompleteCache.setBootComplete();
if (mServicesstarted) {
final int N = mServices.length;
for (int i = 0; i < N; i++) {
mServices[i].onBootCompleted();
}
}
}
}, bootCompletedFilter);
IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
registerReceiver(new broadcastReceiver() {
@OverrIDe
public voID onReceive(Context context, Intent intent) {
if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
if (!mBootCompleteCache.isBootComplete()) return;
// Update names of systemUI notification channels
NotificationChannels.createall(context);
}
}
}, localeChangedFilter);
} else {
// We don't need to startServices for sub-process that is doing some tasks.
// (screenshots, sweetsweetdesserts or tuner ..)
String processname = ActivityThread.currentProcessname();
ApplicationInfo info = getApplicationInfo();
if (processname != null && processname.startsWith(info.processname + ":")) {
return;
}
// For a secondary user, boot-completed will never be called because it has already
// been broadcasted on startup for the primary systemUI process. Instead, for
// components which require the systemUI component to be initialized per-user, we
// start those components Now for the current non-system user.
startSecondaryUserServicesIfNeeded(); 会走这里
}
}
2.
voID startSecondaryUserServicesIfNeeded() {
String[] names = systemUIFactory.getInstance().getsystemUIServiceComponentsPerUser( //这里从config.xml文件里面获取服务名称
getResources());
startServicesIfNeeded(/* metricsPrefix= */ "StartSecondaryServices", names);
}
3.
frameworks/base/packages/systemUI/res/values/config.xml
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.androID.systemUI.util.NotificationChannels</item>
<item>com.androID.systemUI.keyguard.KeyguardVIEwMediator</item>
<item>com.androID.systemUI.recents.Recents</item>
<item>com.androID.systemUI.volume.VolumeUI</item>
<item>com.androID.systemUI.stackdivIDer.divIDer</item>
<item>com.androID.systemUI.statusbar.phone.Statusbar</item>
<item>com.androID.systemUI.usb.StorageNotification</item>
<item>com.androID.systemUI.power.PowerUI</item>
<item>com.androID.systemUI.media.ringtonePlayer</item>
<item>com.androID.systemUI.keyboard.KeyboardUI</item>
<item>com.androID.systemUI.pip.PipUI</item>
<item>com.androID.systemUI.shortcut.ShortcutKeydispatcher</item>
<item>@string/config_systemUIvendorServiceComponent</item>
<item>com.androID.systemUI.util.leak.GarbageMonitor$Service</item>
<item>com.androID.systemUI.LatencyTester</item>
<item>com.androID.systemUI.globalactions.GlobalActionsComponent</item>
<item>com.androID.systemUI.Screendecorations</item>
<item>com.androID.systemUI.biometrics.AuthController</item>
<item>com.androID.systemUI.SlicebroadcastRelayHandler</item>
<item>com.androID.systemUI.SizeCompatModeActivityController</item>
<item>com.androID.systemUI.statusbar.notification.InstantAppNotifIEr</item>
<item>com.androID.systemUI.theme.themeOverlayController</item>
<item>com.androID.systemUI.accessibility.WindowMagnification</item>
<item>com.androID.systemUI.accessibility.SystemActions</item>
<item>com.androID.systemUI.toast.ToastUI</item>
</string-array>
4.
private voID startServicesIfNeeded(String metricsPrefix, String[] services) {
if (mServicesstarted) {
return;
}
mServices = new systemUI[services.length];
if (!mBootCompleteCache.isBootComplete()) {
// check to see if maybe it was already completed long before we began
// see ActivityManagerService.finishBooting()
if ("1".equals(SystemPropertIEs.get("sys.boot_completed"))) {
mBootCompleteCache.setBootComplete();
if (DEBUG) {
Log.v(TAG, "BOOT_COMPLETED was already sent");
}
}
}
final DumpManager dumpManager = mRootComponent.createDumpManager();
Log.v(TAG, "Starting systemUI services for user " +
Process.myUserHandle().getIDentifIEr() + ".");
TimingsTraceLog log = new TimingsTraceLog("systemUIBoottiming",
Trace.TRACE_TAG_APP);
log.traceBegin(metricsPrefix);
final int N = services.length;
for (int i = 0; i < N; i++) {
String clsname = services[i];
if (DEBUG) Log.d(TAG, "loading: " + clsname);
log.traceBegin(metricsPrefix + clsname);
long ti = System.currentTimeMillis();
try {
systemUI obj = mComponentHelper.resolvesystemUI(clsname);
if (obj == null) {
Constructor constructor = Class.forname(clsname).getConstructor(Context.class);
obj = (systemUI) constructor.newInstance(this);
}
mServices[i] = obj;
} catch (ClassNotFoundException
| NoSuchMethodException
| illegalaccessexception
| InstantiationException
| InvocationTargetException ex) {
throw new RuntimeException(ex);
}
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
mServices[i].start(); 这里会启动ringtonePlayer 服务
log.traceEnd();
// Warn if initialization of component takes too long
ti = System.currentTimeMillis() - ti;
if (ti > 1000) {
Log.w(TAG, "Initialization of " + clsname + " took " + ti + " ms");
}
if (mBootCompleteCache.isBootComplete()) {
mServices[i].onBootCompleted();
}
dumpManager.registerDumpable(mServices[i].getClass().getname(), mServices[i]);
}
mRootComponent.getinitController().executePostinitTasks();
log.traceEnd();
mServicesstarted = true;
}
第二步:
frameworks/base/packages/systemUI/src/com/androID/systemUI/media/ringtonePlayer.java
public voID start() {
mAsyncPlayer.setUsesWakeLock(mContext);
mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUdio_SERVICE));
try {
mAudioService.setringtonePlayer(mCallback); mAudioService设置IringtonePlayer的回调
} catch (remoteexception e) {
Log.e(TAG, "Problem registering ringtonePlayer: " + e);
}
}
@OverrIDe
public voID playAsync(Uri uri, UserHandle user, boolean looPing, AudioAttributes aa) {
if (LOGD) Log.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")");
if (Binder.getCallingUID() != Process.SYstem_UID) {
throw new SecurityException("Async playback only available from system UID.");
}
if (UserHandle.ALL.equals(user)) {
user = UserHandle.SYstem;
}
Log.e(TAG, Log.getStackTraceString(new Throwable()));
mAsyncPlayer.play(getContextForUser(user), uri, looPing, aa);
}
第三步:
frameworks/base/services/core/java/com/androID/server/notification/notificationmanagerService.java
if (mAssistants.isEnabled()) {
mAssistants.onNotificationEnqueuedLocked(r);
mHandler.postDelayed(new PostNotificationRunnable(r.getKey()),
DELAY_FOR_ASSISTANT_TIME);
} else {
mHandler.post(new PostNotificationRunnable(r.getKey())); 这里开始PostNotificationRunnable 线程运行
}
final boolean isPackageSuspended =
isPackagePausedOrSuspended(r.getSbn().getPackagename(), r.getUID());
r.setHIDden(isPackageSuspended);
int buzzBeepBlinkLoggingCode = 0;
if (!r.isHIDden()) {
buzzBeepBlinkLoggingCode = buzzBeepBlinkLocked(r);
}
int buzzBeepBlinkLocked(NotificationRecord record) {
Log.e(TAG,"zhanghui buzzBeepBlinkLocked 1.0");
if (mIsautomotive && !mNotificationEffectsEnabledForautomotive) {
return 0;
}
boolean buzz = false;
boolean beep = false;
boolean blink = false;
final Notification notification = record.getSbn().getNotification();
final String key = record.getKey();
Log.e(TAG,"zhanghui buzzBeepBlinkLocked 1.0.0");
// Should this notification make noise, vibe, or use the LED?
final boolean aboveThreshold =
mIsautomotive
? record.getimportance() > notificationmanager.importANCE_DEFAulT
: record.getimportance() >= notificationmanager.importANCE_DEFAulT;
// Remember if this notification already owns the notification channels.
boolean wasBeep = key != null && key.equals(mSoundNotificationKey);
boolean wasBuzz = key != null && key.equals(mVibrateNotificationKey);
// These are set insIDe the conditional if the notification is allowed to make noise.
boolean hasValIDVibrate = false;
boolean hasValIDSound = false;
boolean sentAccessibilityEvent = false;
Log.e(TAG,"zhanghui buzzBeepBlinkLocked 1.1");
// If the notification will appear in the status bar, it should send an accessibility event
final boolean suppressedByDnd = record.isIntercepted()
&& (record.getSuppressedVisualEffects() & SUPpressed_EFFECT_STATUS_bar) != 0;
if (!record.isUpdate
&& record.getimportance() > importANCE_MIN
&& !suppressedByDnd) {
sendAccessibilityEvent(notification, record.getSbn().getPackagename());
sentAccessibilityEvent = true;
}
Log.e(TAG,"zhanghui buzzBeepBlinkLocked 1.2 aboveThreshold="+aboveThreshold);
Log.e(TAG,"zhanghui buzzBeepBlinkLocked 1.2 isNotificationForCurrentUser(record)="+ isNotificationForCurrentUser(record));
if (aboveThreshold && isNotificationForCurrentUser(record)) {
Log.e(TAG,"zhanghui buzzBeepBlinkLocked 1.2 mSystemReady="+mSystemReady);
if(mAudioManager != null){
Log.e(TAG,"zhanghui buzzBeepBlinkLocked mAudioManager is true");
}
if (mSystemReady && mAudioManager != null) {
Uri soundUri = record.getSound();
hasValIDSound = soundUri != null && !Uri.EMPTY.equals(soundUri);
long[] vibration = record.getVibration();
// Demote sound to vibration if vibration missing & phone in vibration mode.
if (vibration == null
&& hasValIDSound
&& (mAudioManager.getRingerModeInternal()
== AudioManager.RINGER_MODE_VIBRATE)
&& mAudioManager.getStreamVolume(
AudioAttributes.tolegacyStreamType(record.getAudioAttributes())) == 0) {
vibration = mFallbackVibrationPattern;
}
hasValIDVibrate = vibration != null;
boolean hasAudibleAlert = hasValIDSound || hasValIDVibrate;
Log.e(TAG,"zhanghui hasAudibleAlert="+hasAudibleAlert);
if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) { //shouldMuteNotificationLocked这里很关键,高通原生第一次升级默认没有提示音(比如:蓝牙传输接收文件没有提示音)
if (!sentAccessibilityEvent) {
sendAccessibilityEvent(notification, record.getSbn().getPackagename());
sentAccessibilityEvent = true;
}
if (DBG) Slog.v(TAG, "Interrupting!");
Log.e(TAG,"zhanghui buzzBeepBlinkLocked 1.2 hasValIDSound="+hasValIDSound);
if (hasValIDSound) {
if (isInCall()) {
playInCallNotification();
beep = true;
} else {
beep = playSound(record, soundUri); 跑这里调用
}
if(beep) {
mSoundNotificationKey = key;
}
}
final boolean ringerModeSilent =
mAudioManager.getRingerModeInternal()
== AudioManager.RINGER_MODE_SILENT;
if (!isInCall() && hasValIDVibrate && !ringerModeSilent) {
buzz = playVibration(record, vibration, hasValIDSound);
if(buzz) {
mVibrateNotificationKey = key;
}
}
} else if ((record.getFlags() & Notification.FLAG_INSISTENT) != 0) {
hasValIDSound = false;
}
}
}
// If a notification is updated to remove the actively playing sound or vibrate,
// cancel that Feedback Now
if (wasBeep && !hasValIDSound) {
clearSoundLocked();
}
if (wasBuzz && !hasValIDVibrate) {
clearVibrateLocked();
}
// light
// release the light
boolean wasShowlights = mlights.remove(key);
if (canShowlightsLocked(record, aboveThreshold)) {
mlights.add(key);
updatelightsLocked();
if (mUseAttentionlight && mAttentionlight != null) {
mAttentionlight.pulse();
}
blink = true;
} else if (wasShowlights) {
updatelightsLocked();
}
final int buzzBeepBlink = (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0);
if (buzzBeepBlink > 0) {
// Ignore summary updates because we don't display most of the information.
if (record.getSbn().isGroup() && record.getSbn().getNotification().isGroupSummary()) {
if (DEBUG_INTERRUPTIVEnesS) {
Slog.v(TAG, "INTERRUPTIVEnesS: "
+ record.getKey() + " is not interruptive: summary");
}
} else if (record.canBubble()) {
if (DEBUG_INTERRUPTIVEnesS) {
Slog.v(TAG, "INTERRUPTIVEnesS: "
+ record.getKey() + " is not interruptive: bubble");
}
} else {
record.setInterruptive(true);
if (DEBUG_INTERRUPTIVEnesS) {
Slog.v(TAG, "INTERRUPTIVEnesS: "
+ record.getKey() + " is interruptive: alerted");
}
}
Metricslogger.action(record.getLogMaker()
.setcategory(MetricsEvent.NOTIFICATION_ALERT)
.setType(MetricsEvent.TYPE_OPEN)
.setSubtype(buzzBeepBlink));
EventLogTags.writeNotificationAlert(key, buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
}
record.setAudiblyAlerted(buzz || beep);
return buzzBeepBlink;
}
private boolean playSound(final NotificationRecord record, Uri soundUri) {
boolean looPing = (record.getNotification().flags & FLAG_INSISTENT) != 0;
// play notifications if there is no user of exclusive audio focus
// and the stream volume is not 0 (non-zero volume implIEs not silenced by SILENT or
// VIBRATE ringer mode)
if (!mAudioManager.isAudioFocusExclusive()
&& (mAudioManager.getStreamVolume(
AudioAttributes.tolegacyStreamType(record.getAudioAttributes())) != 0)) {
final long IDentity = Binder.clearCallingIDentity();
try {
final IringtonePlayer player = mAudioManager.getringtonePlayer();
if (player != null) {
if (true) Slog.v(TAG, "zhanghui Playing sound " + soundUri
+ " with attributes " + record.getAudioAttributes());
Log.e(TAG, Log.getStackTraceString(new Throwable()));
player.playAsync(soundUri, record.getSbn().getUser(), looPing, 这里跑到第二步的ringtonePlayer回调函数的playAsync,这里传入的soundUri 就是后面播放的提示音文件缓存
record.getAudioAttributes());
return true;
}
} catch (remoteexception e) {
} finally {
Binder.restoreCallingIDentity(IDentity);
}
}
return false;
}
第四步:
frameworks/base/packages/systemUI/src/com/androID/systemUI/media/ringtonePlayer.java
public voID start() {
mAsyncPlayer.setUsesWakeLock(mContext);
mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUdio_SERVICE));
try {
mAudioService.setringtonePlayer(mCallback); mAudioService设置IringtonePlayer的回调
} catch (remoteexception e) {
Log.e(TAG, "Problem registering ringtonePlayer: " + e);
}
}
@OverrIDe
public voID playAsync(Uri uri, UserHandle user, boolean looPing, AudioAttributes aa) {
if (LOGD) Log.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")");
if (Binder.getCallingUID() != Process.SYstem_UID) {
throw new SecurityException("Async playback only available from system UID.");
}
if (UserHandle.ALL.equals(user)) {
user = UserHandle.SYstem;
}
Log.e(TAG, Log.getStackTraceString(new Throwable()));
mAsyncPlayer.play(getContextForUser(user), uri, looPing, aa); 这里跑到NotificationPlayer类的play()
}
frameworks/base/packages/systemUI/src/com/androID/systemUI/media/NotificationPlayer.java
public voID play(Context context, Uri uri, boolean looPing, AudioAttributes attributes) {
if (DEBUG) { Log.d(mTag, "play uri=" + uri.toString()); }
Command cmd = new Command();
cmd.requestTime = SystemClock.uptimeMillis();
cmd.code = PLAY;
cmd.context = context;
cmd.uri = uri;
cmd.looPing = looPing;
cmd.attributes = attributes;
synchronized (mCmdQueue) {
enqueueLocked(cmd);
mState = PLAY;
}
}
private voID enqueueLocked(Command cmd) {
mCmdQueue.add(cmd);
if (mThread == null) {
acquireWakeLock();
mThread = new CmdThread();
mThread.start();
}
}
private final class CmdThread extends java.lang.Thread {
CmdThread() {
super("NotificationPlayer-" + mTag);
}
public voID run() {
while (true) {
Command cmd = null;
synchronized (mCmdQueue) {
if (DEBUG) Log.d(mTag, "RemoveFirst");
cmd = mCmdQueue.removeFirst();
}
switch (cmd.code) {
case PLAY:
if (DEBUG) Log.d(mTag, "PLAY");
startSound(cmd); 这里跑到CreationAndCompletionThread 线程
break;
case Stop:
if (DEBUG) Log.d(mTag, "Stop");
final MediaPlayer mp;
synchronized (mPlayerLock) {
mp = mPlayer;
mPlayer = null;
}
if (mp != null) {
long delay = SystemClock.uptimeMillis() - cmd.requestTime;
if (delay > 1000) {
Log.w(mTag, "Notification stop delayed by " + delay + "msecs");
}
try {
mp.stop();
} catch (Exception e) { }
mp.release();
synchronized(mQueueAudioFocusLock) {
if (mAudioManagerWithAudioFocus != null) {
if (DEBUG) { Log.d(mTag, "in Stop: abandonning AudioFocus"); }
mAudioManagerWithAudioFocus.abandonAudioFocus(null);
mAudioManagerWithAudioFocus = null;
}
}
synchronized (mCompletionHandlingLock) {
if ((mLooper != null) &&
(mLooper.getThread().getState() != Thread.State.TERMINATED))
{
if (DEBUG) { Log.d(mTag, "in Stop: quitting looper "+ mLooper); }
mLooper.quit();
}
}
} else {
Log.w(mTag, "Stop command without a player");
}
break;
}
private final class CreationAndCompletionThread extends Thread {
public Command mCmd;
public CreationAndCompletionThread(Command cmd) {
super();
mCmd = cmd;
}
public voID run() {
Looper.prepare();
// ok to modify mLooper as here we are
// synchronized on mCompletionHandlingLock due to the Object.wait() in startSound(cmd)
mLooper = Looper.myLooper();
if (DEBUG) Log.d(mTag, "in run: new looper " + mLooper);
MediaPlayer player = null;
synchronized(this) {
AudioManager audioManager =
(AudioManager) mCmd.context.getSystemService(Context.AUdio_SERVICE);
try {
player = new MediaPlayer();
if (mCmd.attributes == null) {
mCmd.attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
}
player.setAudioAttributes(mCmd.attributes);
player.setDataSource(mCmd.context, mCmd.uri); 这里调用了MediaPlayer里面的setDataSource
player.setLooPing(mCmd.looPing);
player.setonCompletionListener(NotificationPlayer.this);
player.setonErrorListener(NotificationPlayer.this);
player.prepare();
if ((mCmd.uri != null) && (mCmd.uri.getEncodedpath() != null)
&& (mCmd.uri.getEncodedpath().length() > 0)) {
if (!audioManager.isMusicActiveRemotely()) {
synchronized (mQueueAudioFocusLock) {
if (mAudioManagerWithAudioFocus == null) {
if (DEBUG) Log.d(mTag, "requesting AudioFocus");
int focusGain = AudioManager.AUdioFOCUS_GAIN_TRANSIENT_MAY_DUCK;
if (mCmd.looPing) {
focusGain = AudioManager.AUdioFOCUS_GAIN;
}
mNotificationRampTimeMs = audioManager.getFocusRampTimeMs(
focusGain, mCmd.attributes);
audioManager.requestAudioFocus(null, mCmd.attributes,
focusGain, 0);
mAudioManagerWithAudioFocus = audioManager;
} else {
if (DEBUG) Log.d(mTag, "AudioFocus was prevIoUsly requested");
}
}
}
}
// FIXME Having to start a new thread so we can receive completion callbacks
// is wrong, as we kill this thread whenever a new sound is to be played. This
// can lead to AudioFocus being released too early, before the second sound is
// done playing. This class should be modifIEd to use a single thread, on which
// command are issued, and on which it receives the completion callbacks.
if (DEBUG) { Log.d(mTag, "notification will be delayed by "
+ mNotificationRampTimeMs + "ms"); }
try {
Thread.sleep(mNotificationRampTimeMs);
} catch (InterruptedException e) {
Log.e(mTag, "Exception while sleePing to sync notification playback"
+ " with ducking", e);
}
player.start();
if (DEBUG) { Log.d(mTag, "player.start"); }
} catch (Exception e) {
if (player != null) {
player.release();
player = null;
}
Log.w(mTag, "error loading sound for " + mCmd.uri, e);
// playing the notification dIDn't work, revert the focus request
abandonAudioFocusAfterError();
}
final MediaPlayer mp;
synchronized (mPlayerLock) {
mp = mPlayer;
mPlayer = player;
}
if (mp != null) {
if (DEBUG) { Log.d(mTag, "mPlayer.release"); }
mp.release();
}
this.notify();
}
Looper.loop();
}
};
frameworks/base/media/java/androID/media/MediaPlayer.java
private boolean attemptDataSource(ContentResolver resolver, Uri uri) {
try (AssetfileDescriptor afd = resolver.openAssetfileDescriptor(uri, "r")) { 这里跑到了ContentResolver里面的openAssetfileDescriptor
setDataSource(afd);
return true;
} catch (NullPointerException | SecurityException | IOException ex) {
return false;
}
}
public voID setDataSource(String path)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(path, null, null);
}
public voID setDataSource(@NonNull Context context, @NonNull Uri uri)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(context, uri, null, null);
}
private voID setDataSource(String path, String[] keys, String[] values,
List<httpcookie> cookies)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
final Uri uri = Uri.parse(path);
final String scheme = uri.getScheme();
if ("file".equals(scheme)) {
path = uri.getPath();
Log.e(TAG,"zhanghui path="+path);
} else if (scheme != null) {
// handle non-file sources
nativeSetDataSource(
MediahttpService.createhttpServiceBinderIfNecessary(path, cookies),
path,
keys,
values);
return;
}
final file file = new file(path);
try (fileinputStream is = new fileinputStream(file)) {
Log.e(TAG,"zhanghui is.getFD()="+is.getFD());
setDataSource(is.getFD());
}
}
frameworks/base/core/java/androID/content/ContentResolver.java
public final @Nullable AssetfileDescriptor openAssetfileDescriptor(@NonNull Uri uri,
@NonNull String mode) throws fileNotFoundException {
return openAssetfileDescriptor(uri, mode, null);
}
public final @Nullable AssetfileDescriptor openAssetfileDescriptor(@NonNull Uri uri,
@NonNull String mode, @Nullable CancellationSignal cancellationSignal)
throws fileNotFoundException {
Objects.requireNonNull(uri, "uri");
Objects.requireNonNull(mode, "mode");
try {
if (mWrapped != null) return mWrapped.openAssetfile(uri, mode, cancellationSignal);
} catch (remoteexception e) {
return null;
}
String scheme = uri.getScheme();
if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
if (!"r".equals(mode)) {
throw new fileNotFoundException("Can't write resources: " + uri);
}
OpenResourceIDResult r = getResourceID(uri);
try {
return r.r.openRawResourceFd(r.ID);
} catch (Resources.NotFoundException ex) {
throw new fileNotFoundException("Resource does not exist: " + uri);
}
} else if (SCHEME_file.equals(scheme)) {
ParcelfileDescriptor pfd = ParcelfileDescriptor.open(
new file(uri.getPath()), ParcelfileDescriptor.parseMode(mode));
return new AssetfileDescriptor(pfd, 0, -1);
} else {
if ("r".equals(mode)) {
return openTypedAssetfileDescriptor(uri, "*/*", null, cancellationSignal);
} else {
IContentProvIDer unstableProvIDer = acquireUnstableProvIDer(uri);
if (unstableProvIDer == null) {
throw new fileNotFoundException("No content provIDer: " + uri);
}
IContentProvIDer stableProvIDer = null;
AssetfileDescriptor fd = null;
try {
ICancellationSignal remoteCancellationSignal = null;
if (cancellationSignal != null) {
cancellationSignal.throwIfCanceled();
remoteCancellationSignal = unstableProvIDer.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
try {
fd = unstableProvIDer.openAssetfile(
mPackagename, mAttributionTag, uri, mode,
remoteCancellationSignal);
if (fd == null) {
// The provIDer will be released by the finally{} clause
return null;
}
} catch (DeadobjectException e) {
// The remote process has dIEd... but we only hold an unstable
// reference though, so we might recover!!! Let's try!!!!
// This is exciting!!1!!1!!!!1
unstableProvIDerDIEd(unstableProvIDer);
stableProvIDer = acquireProvIDer(uri);
if (stableProvIDer == null) {
throw new fileNotFoundException("No content provIDer: " + uri);
}
fd = stableProvIDer.openAssetfile(
mPackagename, mAttributionTag, uri, mode, remoteCancellationSignal);
if (fd == null) {
// The provIDer will be released by the finally{} clause
return null;
}
}
if (stableProvIDer == null) {
stableProvIDer = acquireProvIDer(uri);
}
releaseUnstableProvIDer(unstableProvIDer);
unstableProvIDer = null;
ParcelfileDescriptor pfd = new ParcelfileDescriptorInner(
fd.getParcelfileDescriptor(), stableProvIDer);
// Success! Don't release the provIDer when exiting, let
// ParcelfileDescriptorInner do that when it is closed.
stableProvIDer = null;
return new AssetfileDescriptor(pfd, fd.getStartOffset(),
fd.getDeclaredLength());
} catch (remoteexception e) {
// Whatever, whatever, we'll go away.
throw new fileNotFoundException(
"Failed opening content provIDer: " + uri);
} catch (fileNotFoundException e) {
throw e;
} finally {
if (cancellationSignal != null) {
cancellationSignal.setRemote(null);
}
if (stableProvIDer != null) {
releaseProvIDer(stableProvIDer);
}
if (unstableProvIDer != null) {
releaseUnstableProvIDer(unstableProvIDer);
}
}
}
}
}
总结
以上是内存溢出为你收集整理的android系统 默认提示音控制流程全部内容,希望文章能够帮你解决android系统 默认提示音控制流程所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)