下面列出了android.util.Pair#create ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public void onKeyDown(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - considering " + keyEvent);
}
final Pair<Integer, Integer> key =
Pair.create(keyEvent.getKeyCode(), keyEvent.getMetaState());
if (mKeySet.contains(key)) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - enabling action");
}
mCanFire = true;
mMetaState = keyEvent.getMetaState();
} else if (mCanFire) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - disabling action");
}
mCanFire = false;
}
}
@Override
@RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
public Bundle getCache(String packageName, Uri key, int userId) {
enforceCrossUserPermission(userId, TAG);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG);
mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
packageName);
final String providerPackageName = getProviderPackageName(key);
final Pair<String, Uri> fullKey = Pair.create(packageName, key);
synchronized (mCache) {
final ArrayMap<Pair<String, Uri>, Bundle> cache = findOrCreateCacheLocked(userId,
providerPackageName);
return cache.get(fullKey);
}
}
private static Pair<String, String[]> buildSharedFileSelectorArgs(@NonNull String newHash,
@Nullable AttachmentId attachmentId)
{
final String selector;
final String[] selection;
if (attachmentId == null) {
selector = DATA_HASH + " = ?";
selection = new String[]{newHash};
} else {
selector = PART_ID_WHERE_NOT + " AND " + DATA_HASH + " = ?";
selection = new String[]{Long.toString(attachmentId.getRowId()),
Long.toString(attachmentId.getUniqueId()),
newHash};
}
return Pair.create(selector, selection);
}
/**
* Parses a single Event node in the manifest.
*
* @param xpp The current xml parser.
* @param schemeIdUri The schemeIdUri of the parent EventStream.
* @param value The schemeIdUri of the parent EventStream.
* @param timescale The timescale of the parent EventStream.
* @param scratchOutputStream A {@link ByteArrayOutputStream} that is used when parsing event
* objects.
* @return A pair containing the node's presentation timestamp in microseconds and the parsed
* {@link EventMessage}.
* @throws XmlPullParserException If there is any error parsing this node.
* @throws IOException If there is any error reading from the underlying input stream.
*/
protected Pair<Long, EventMessage> parseEvent(
XmlPullParser xpp,
String schemeIdUri,
String value,
long timescale,
ByteArrayOutputStream scratchOutputStream)
throws IOException, XmlPullParserException {
long id = parseLong(xpp, "id", 0);
long duration = parseLong(xpp, "duration", C.TIME_UNSET);
long presentationTime = parseLong(xpp, "presentationTime", 0);
long durationMs = Util.scaleLargeTimestamp(duration, C.MILLIS_PER_SECOND, timescale);
long presentationTimesUs = Util.scaleLargeTimestamp(presentationTime, C.MICROS_PER_SECOND,
timescale);
String messageData = parseString(xpp, "messageData", null);
byte[] eventObject = parseEventObject(xpp, scratchOutputStream);
return Pair.create(
presentationTimesUs,
buildEvent(
schemeIdUri,
value,
id,
durationMs,
messageData == null ? eventObject : Util.getUtf8Bytes(messageData)));
}
@Override
@RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
public void putCache(String packageName, Uri key, Bundle value, int userId) {
Bundle.setDefusable(value, true);
enforceCrossUserPermission(userId, TAG);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG);
mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
packageName);
final String providerPackageName = getProviderPackageName(key);
final Pair<String, Uri> fullKey = Pair.create(packageName, key);
synchronized (mCache) {
final ArrayMap<Pair<String, Uri>, Bundle> cache = findOrCreateCacheLocked(userId,
providerPackageName);
if (value != null) {
cache.put(fullKey, value);
} else {
cache.remove(fullKey);
}
}
}
@Nullable
@Override
public Pair<Boolean, Integer> onResponse(@NonNull String response) {
if (callback != null) {
callback.run(response);
}
RequestResult result = RequestResult.parseJson(response);
if (result.isSuccess() && result.getResponse().has("waitTime")) {
String orderId = result.getResponse().optString("orderId");
int waitTime = Utils.parseInt(result.getResponse().optString("waitTime"));
if (!TextUtils.isEmpty(orderId)) {
return Pair.create(true, -1);
}
return Pair.create(false, waitTime);
}
return Pair.create(false, -1);
}
private static Pair<float[], float[]> insertControlPoint(
float[] luxLevels, float[] brightnessLevels, float lux, float brightness) {
final int idx = findInsertionPoint(luxLevels, lux);
final float[] newLuxLevels;
final float[] newBrightnessLevels;
if (idx == luxLevels.length) {
newLuxLevels = Arrays.copyOf(luxLevels, luxLevels.length + 1);
newBrightnessLevels = Arrays.copyOf(brightnessLevels, brightnessLevels.length + 1);
newLuxLevels[idx] = lux;
newBrightnessLevels[idx] = brightness;
} else if (luxLevels[idx] == lux) {
newLuxLevels = Arrays.copyOf(luxLevels, luxLevels.length);
newBrightnessLevels = Arrays.copyOf(brightnessLevels, brightnessLevels.length);
newBrightnessLevels[idx] = brightness;
} else {
newLuxLevels = Arrays.copyOf(luxLevels, luxLevels.length + 1);
System.arraycopy(newLuxLevels, idx, newLuxLevels, idx+1, luxLevels.length - idx);
newLuxLevels[idx] = lux;
newBrightnessLevels = Arrays.copyOf(brightnessLevels, brightnessLevels.length + 1);
System.arraycopy(newBrightnessLevels, idx, newBrightnessLevels, idx+1,
brightnessLevels.length - idx);
newBrightnessLevels[idx] = brightness;
}
smoothCurve(newLuxLevels, newBrightnessLevels, idx);
return Pair.create(newLuxLevels, newBrightnessLevels);
}
private static Pair<float[], float[]> loadCurveFromXml(XmlPullParser parser)
throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
List<Float> luxLevels = new ArrayList<>();
List<Float> nitLevels = new ArrayList<>();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
if (TAG_BRIGHTNESS_POINT.equals(parser.getName())) {
luxLevels.add(loadFloat(parser.getAttributeValue(null, ATTR_LUX)));
nitLevels.add(loadFloat(parser.getAttributeValue(null, ATTR_NITS)));
}
}
final int N = luxLevels.size();
float[] lux = new float[N];
float[] nits = new float[N];
for (int i = 0; i < N; i++) {
lux[i] = luxLevels.get(i);
nits[i] = nitLevels.get(i);
}
return Pair.create(lux, nits);
}
/**
* Converts (windowIndex, windowPositionUs) to the corresponding (periodIndex, periodPositionUs).
*
* @param window A {@link Window} that may be overwritten.
* @param period A {@link Period} that may be overwritten.
* @param windowIndex The window index.
* @param windowPositionUs The window time, or {@link C#TIME_UNSET} to use the window's default
* start position.
* @param defaultPositionProjectionUs If {@code windowPositionUs} is {@link C#TIME_UNSET}, the
* duration into the future by which the window's position should be projected.
* @return The corresponding (periodIndex, periodPositionUs), or null if {@code #windowPositionUs}
* is {@link C#TIME_UNSET}, {@code defaultPositionProjectionUs} is non-zero, and the window's
* position could not be projected by {@code defaultPositionProjectionUs}.
*/
public final Pair<Integer, Long> getPeriodPosition(Window window, Period period, int windowIndex,
long windowPositionUs, long defaultPositionProjectionUs) {
Assertions.checkIndex(windowIndex, 0, getWindowCount());
getWindow(windowIndex, window, false, defaultPositionProjectionUs);
if (windowPositionUs == C.TIME_UNSET) {
windowPositionUs = window.getDefaultPositionUs();
if (windowPositionUs == C.TIME_UNSET) {
return null;
}
}
int periodIndex = window.firstPeriodIndex;
long periodPositionUs = window.getPositionInFirstPeriodUs() + windowPositionUs;
long periodDurationUs = getPeriod(periodIndex, period).getDurationUs();
while (periodDurationUs != C.TIME_UNSET && periodPositionUs >= periodDurationUs
&& periodIndex < window.lastPeriodIndex) {
periodPositionUs -= periodDurationUs;
periodDurationUs = getPeriod(++periodIndex, period).getDurationUs();
}
return Pair.create(periodIndex, periodPositionUs);
}
public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Uri uri,
Account account) throws RemoteException {
Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT,
new String[]{account.name, account.type}, null);
if (c == null) {
throw new RemoteException();
}
try {
if (c.moveToNext()) {
long rowId = c.getLong(1);
byte[] blob = c.getBlob(c.getColumnIndexOrThrow(Columns.DATA));
return Pair.create(ContentUris.withAppendedId(uri, rowId), blob);
}
} finally {
c.close();
}
return null;
}
/**
* 找到参数里面的第一个Intent 对象,返回该Intent的索引和该Intent对象
*/
private Pair<Integer, Intent> foundFirstIntentOfArgs(Object... args) {
int index = 0;
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Intent) {
index = i;
break;
}
}
if (args[index] instanceof Intent) {
return Pair.create(index, (Intent) args[index]);
} else {
return Pair.create(index, null);
}
}
private static Pair<float[], float[]> getAdjustedCurve(float[] lux, float[] brightness,
float userLux, float userBrightness, float adjustment, float maxGamma) {
float[] newLux = lux;
float[] newBrightness = Arrays.copyOf(brightness, brightness.length);
if (DEBUG) {
PLOG.logCurve("unadjusted curve", newLux, newBrightness);
}
adjustment = MathUtils.constrain(adjustment, -1, 1);
float gamma = MathUtils.pow(maxGamma, -adjustment);
if (DEBUG) {
Slog.d(TAG, "getAdjustedCurve: " + maxGamma + "^" + -adjustment + "=" +
MathUtils.pow(maxGamma, -adjustment) + " == " + gamma);
}
if (gamma != 1) {
for (int i = 0; i < newBrightness.length; i++) {
newBrightness[i] = MathUtils.pow(newBrightness[i], gamma);
}
}
if (DEBUG) {
PLOG.logCurve("gamma adjusted curve", newLux, newBrightness);
}
if (userLux != -1) {
Pair<float[], float[]> curve = insertControlPoint(newLux, newBrightness, userLux,
userBrightness);
newLux = curve.first;
newBrightness = curve.second;
if (DEBUG) {
PLOG.logCurve("gamma and user adjusted curve", newLux, newBrightness);
// This is done for comparison.
curve = insertControlPoint(lux, brightness, userLux, userBrightness);
PLOG.logCurve("user adjusted curve", curve.first ,curve.second);
}
}
return Pair.create(newLux, newBrightness);
}
protected Pair<Period, Long> parsePeriod(XmlPullParser xpp, String baseUrl, long defaultStartMs)
throws XmlPullParserException, IOException {
String id = xpp.getAttributeValue(null, "id");
long startMs = parseDuration(xpp, "start", defaultStartMs);
long durationMs = parseDuration(xpp, "duration", C.TIME_UNSET);
SegmentBase segmentBase = null;
List<AdaptationSet> adaptationSets = new ArrayList<>();
List<EventStream> eventStreams = new ArrayList<>();
boolean seenFirstBaseUrl = false;
do {
xpp.next();
if (XmlPullParserUtil.isStartTag(xpp, "BaseURL")) {
if (!seenFirstBaseUrl) {
baseUrl = parseBaseUrl(xpp, baseUrl);
seenFirstBaseUrl = true;
}
} else if (XmlPullParserUtil.isStartTag(xpp, "AdaptationSet")) {
adaptationSets.add(parseAdaptationSet(xpp, baseUrl, segmentBase));
} else if (XmlPullParserUtil.isStartTag(xpp, "EventStream")) {
eventStreams.add(parseEventStream(xpp));
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentBase")) {
segmentBase = parseSegmentBase(xpp, null);
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentList")) {
segmentBase = parseSegmentList(xpp, null);
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) {
segmentBase = parseSegmentTemplate(xpp, null);
}
} while (!XmlPullParserUtil.isEndTag(xpp, "Period"));
return Pair.create(buildPeriod(id, startMs, adaptationSets, eventStreams), durationMs);
}
@Override
public final Period getPeriod(int periodIndex, Period period, boolean setIds) {
int childIndex = getChildIndexByPeriodIndex(periodIndex);
int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex);
int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex);
getTimelineByChildIndex(childIndex).getPeriod(periodIndex - firstPeriodIndexInChild, period,
setIds);
period.windowIndex += firstWindowIndexInChild;
if (setIds) {
period.uid = Pair.create(getChildUidByChildIndex(childIndex), period.uid);
}
return period;
}
/**
* Parses an ALAC AudioSpecificConfig (i.e. an <a
* href="https://github.com/macosforge/alac/blob/master/ALACMagicCookieDescription.txt">ALACSpecificConfig</a>).
*
* @param audioSpecificConfig A byte array containing the AudioSpecificConfig to parse.
* @return A pair consisting of the sample rate in Hz and the channel count.
*/
public static Pair<Integer, Integer> parseAlacAudioSpecificConfig(byte[] audioSpecificConfig) {
ParsableByteArray byteArray = new ParsableByteArray(audioSpecificConfig);
byteArray.setPosition(9);
int channelCount = byteArray.readUnsignedByte();
byteArray.setPosition(20);
int sampleRate = byteArray.readUnsignedIntToInt();
return Pair.create(sampleRate, channelCount);
}
/**
* Gets the Lutron URI or an empty string
*/
public final Pair<String, String> geLutronCookieValue() {
SessionInfo sessionInfo = getSessionInfo();
if (sessionInfo != null) {
return Pair.create(sessionInfo.getLutronLoginBaseUrl(), "irisAuthToken=" + sessionInfo.getSessionToken());
}
return Pair.create("", "");
}
/**
* Parses the {@link Format} and frame duration from a csd buffer.
*
* @param csdBuffer The csd buffer.
* @param formatId The id for the generated format. May be null.
* @return A pair consisting of the {@link Format} and the frame duration in microseconds, or
* 0 if the duration could not be determined.
*/
private static Pair<Format, Long> parseCsdBuffer(CsdBuffer csdBuffer, String formatId) {
byte[] csdData = Arrays.copyOf(csdBuffer.data, csdBuffer.length);
int firstByte = csdData[4] & 0xFF;
int secondByte = csdData[5] & 0xFF;
int thirdByte = csdData[6] & 0xFF;
int width = (firstByte << 4) | (secondByte >> 4);
int height = (secondByte & 0x0F) << 8 | thirdByte;
float pixelWidthHeightRatio = 1f;
int aspectRatioCode = (csdData[7] & 0xF0) >> 4;
switch(aspectRatioCode) {
case 2:
pixelWidthHeightRatio = (4 * height) / (float) (3 * width);
break;
case 3:
pixelWidthHeightRatio = (16 * height) / (float) (9 * width);
break;
case 4:
pixelWidthHeightRatio = (121 * height) / (float) (100 * width);
break;
default:
// Do nothing.
break;
}
Format format = Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_MPEG2, null,
Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE,
Collections.singletonList(csdData), Format.NO_VALUE, pixelWidthHeightRatio, null);
long frameDurationUs = 0;
int frameRateCodeMinusOne = (csdData[7] & 0x0F) - 1;
if (0 <= frameRateCodeMinusOne && frameRateCodeMinusOne < FRAME_RATE_VALUES.length) {
double frameRate = FRAME_RATE_VALUES[frameRateCodeMinusOne];
int sequenceExtensionPosition = csdBuffer.sequenceExtensionPosition;
int frameRateExtensionN = (csdData[sequenceExtensionPosition + 9] & 0x60) >> 5;
int frameRateExtensionD = (csdData[sequenceExtensionPosition + 9] & 0x1F);
if (frameRateExtensionN != frameRateExtensionD) {
frameRate *= (frameRateExtensionN + 1d) / (frameRateExtensionD + 1);
}
frameDurationUs = (long) (C.MICROS_PER_SECOND / frameRate);
}
return Pair.create(format, frameDurationUs);
}
/**
* Parses an AAC AudioSpecificConfig, as defined in ISO 14496-3 1.6.2.1
*
* @param bitArray A {@link ParsableBitArray} containing the AudioSpecificConfig to parse. The
* position is advanced to the end of the AudioSpecificConfig.
* @param forceReadToEnd Whether the entire AudioSpecificConfig should be read. Required for
* knowing the length of the configuration payload.
* @return A pair consisting of the sample rate in Hz and the channel count.
* @throws ParserException If the AudioSpecificConfig cannot be parsed as it's not supported.
*/
public static Pair<Integer, Integer> parseAacAudioSpecificConfig(
ParsableBitArray bitArray, boolean forceReadToEnd) throws ParserException {
int audioObjectType = getAacAudioObjectType(bitArray);
int sampleRate = getAacSamplingFrequency(bitArray);
int channelConfiguration = bitArray.readBits(4);
if (audioObjectType == AUDIO_OBJECT_TYPE_SBR || audioObjectType == AUDIO_OBJECT_TYPE_PS) {
// For an AAC bitstream using spectral band replication (SBR) or parametric stereo (PS) with
// explicit signaling, we return the extension sampling frequency as the sample rate of the
// content; this is identical to the sample rate of the decoded output but may differ from
// the sample rate set above.
// Use the extensionSamplingFrequencyIndex.
sampleRate = getAacSamplingFrequency(bitArray);
audioObjectType = getAacAudioObjectType(bitArray);
if (audioObjectType == AUDIO_OBJECT_TYPE_ER_BSAC) {
// Use the extensionChannelConfiguration.
channelConfiguration = bitArray.readBits(4);
}
}
if (forceReadToEnd) {
switch (audioObjectType) {
case 1:
case 2:
case 3:
case 4:
case 6:
case 7:
case 17:
case 19:
case 20:
case 21:
case 22:
case 23:
parseGaSpecificConfig(bitArray, audioObjectType, channelConfiguration);
break;
default:
throw new ParserException("Unsupported audio object type: " + audioObjectType);
}
switch (audioObjectType) {
case 17:
case 19:
case 20:
case 21:
case 22:
case 23:
int epConfig = bitArray.readBits(2);
if (epConfig == 2 || epConfig == 3) {
throw new ParserException("Unsupported epConfig: " + epConfig);
}
break;
}
}
// For supported containers, bits_to_decode() is always 0.
int channelCount = AUDIO_SPECIFIC_CONFIG_CHANNEL_COUNT_TABLE[channelConfiguration];
Assertions.checkArgument(channelCount != AUDIO_SPECIFIC_CONFIG_CHANNEL_CONFIGURATION_INVALID);
return Pair.create(sampleRate, channelCount);
}
private Pair<AuthorityInfo, SyncStatusInfo> createCopyPairOfAuthorityWithSyncStatusLocked(
AuthorityInfo authorityInfo) {
SyncStatusInfo syncStatusInfo = getOrCreateSyncStatusLocked(authorityInfo.ident);
return Pair.create(new AuthorityInfo(authorityInfo), new SyncStatusInfo(syncStatusInfo));
}
/**
* Called by {@link #selectAllTracks(MappedTrackInfo, int[][][], int[], Parameters)} to create a
* {@link TrackSelection} for an audio renderer.
*
* @param groups The {@link TrackGroupArray} mapped to the renderer.
* @param formatSupports The {@link Capabilities} for each mapped track, indexed by renderer,
* track group and track (in that order).
* @param mixedMimeTypeAdaptationSupports The {@link AdaptiveSupport} for mixed MIME type
* adaptation for the renderer.
* @param params The selector's current constraint parameters.
* @param enableAdaptiveTrackSelection Whether adaptive track selection is allowed.
* @return The {@link TrackSelection.Definition} and corresponding {@link AudioTrackScore}, or
* null if no selection was made.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
@SuppressWarnings("unused")
@Nullable
protected Pair<TrackSelection.Definition, AudioTrackScore> selectAudioTrack(
TrackGroupArray groups,
@Capabilities int[][] formatSupports,
@AdaptiveSupport int mixedMimeTypeAdaptationSupports,
Parameters params,
boolean enableAdaptiveTrackSelection)
throws ExoPlaybackException {
int selectedTrackIndex = C.INDEX_UNSET;
int selectedGroupIndex = C.INDEX_UNSET;
AudioTrackScore selectedTrackScore = null;
for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
TrackGroup trackGroup = groups.get(groupIndex);
@Capabilities int[] trackFormatSupport = formatSupports[groupIndex];
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
if (isSupported(trackFormatSupport[trackIndex],
params.exceedRendererCapabilitiesIfNecessary)) {
Format format = trackGroup.getFormat(trackIndex);
AudioTrackScore trackScore =
new AudioTrackScore(format, params, trackFormatSupport[trackIndex]);
if (!trackScore.isWithinConstraints && !params.exceedAudioConstraintsIfNecessary) {
// Track should not be selected.
continue;
}
if (selectedTrackScore == null || trackScore.compareTo(selectedTrackScore) > 0) {
selectedGroupIndex = groupIndex;
selectedTrackIndex = trackIndex;
selectedTrackScore = trackScore;
}
}
}
}
if (selectedGroupIndex == C.INDEX_UNSET) {
return null;
}
TrackGroup selectedGroup = groups.get(selectedGroupIndex);
TrackSelection.Definition definition = null;
if (!params.forceHighestSupportedBitrate
&& !params.forceLowestBitrate
&& enableAdaptiveTrackSelection) {
// If the group of the track with the highest score allows it, try to enable adaptation.
int[] adaptiveTracks =
getAdaptiveAudioTracks(
selectedGroup,
formatSupports[selectedGroupIndex],
params.maxAudioBitrate,
params.allowAudioMixedMimeTypeAdaptiveness,
params.allowAudioMixedSampleRateAdaptiveness,
params.allowAudioMixedChannelCountAdaptiveness);
if (adaptiveTracks.length > 0) {
definition = new TrackSelection.Definition(selectedGroup, adaptiveTracks);
}
}
if (definition == null) {
// We didn't make an adaptive selection, so make a fixed one instead.
definition = new TrackSelection.Definition(selectedGroup, selectedTrackIndex);
}
return Pair.create(definition, Assertions.checkNotNull(selectedTrackScore));
}