diff options
Diffstat (limited to 'java')
17 files changed, 204 insertions, 30 deletions
diff --git a/java/com/android/contacts/common/preference/ContactsPreferences.java b/java/com/android/contacts/common/preference/ContactsPreferences.java index 7f0d99acd..2bdf5c82a 100644 --- a/java/com/android/contacts/common/preference/ContactsPreferences.java +++ b/java/com/android/contacts/common/preference/ContactsPreferences.java @@ -27,6 +27,7 @@ import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import com.android.contacts.common.R; import com.android.contacts.common.model.account.AccountWithDataSet; +import com.android.dialer.strictmode.DialerStrictMode; /** Manages user preferences for contacts. */ public class ContactsPreferences implements OnSharedPreferenceChangeListener { @@ -77,11 +78,11 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener { maybeMigrateSystemSettings(); } - public boolean isSortOrderUserChangeable() { + private boolean isSortOrderUserChangeable() { return mContext.getResources().getBoolean(R.bool.config_sort_order_user_changeable); } - public int getDefaultSortOrder() { + private int getDefaultSortOrder() { if (mContext.getResources().getBoolean(R.bool.config_default_sort_order_primary)) { return SORT_ORDER_PRIMARY; } else { @@ -103,14 +104,14 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener { mSortOrder = sortOrder; final Editor editor = mPreferences.edit(); editor.putInt(SORT_ORDER_KEY, sortOrder); - editor.commit(); + DialerStrictMode.bypass(editor::commit); } - public boolean isDisplayOrderUserChangeable() { + private boolean isDisplayOrderUserChangeable() { return mContext.getResources().getBoolean(R.bool.config_display_order_user_changeable); } - public int getDefaultDisplayOrder() { + private int getDefaultDisplayOrder() { if (mContext.getResources().getBoolean(R.bool.config_default_display_order_primary)) { return DISPLAY_ORDER_PRIMARY; } else { @@ -132,14 +133,14 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener { mDisplayOrder = displayOrder; final Editor editor = mPreferences.edit(); editor.putInt(DISPLAY_ORDER_KEY, displayOrder); - editor.commit(); + DialerStrictMode.bypass(editor::commit); } - public boolean isDefaultAccountUserChangeable() { + private boolean isDefaultAccountUserChangeable() { return mContext.getResources().getBoolean(R.bool.config_default_account_user_changeable); } - public String getDefaultAccount() { + private String getDefaultAccount() { if (!isDefaultAccountUserChangeable()) { return mDefaultAccount; } @@ -153,7 +154,7 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener { return mDefaultAccount; } - public void setDefaultAccount(AccountWithDataSet accountWithDataSet) { + private void setDefaultAccount(AccountWithDataSet accountWithDataSet) { mDefaultAccount = accountWithDataSet == null ? null : accountWithDataSet.name; final Editor editor = mPreferences.edit(); if (TextUtils.isEmpty(mDefaultAccount)) { @@ -162,7 +163,7 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener { editor.putString(mDefaultAccountKey, accountWithDataSet.stringify()); } editor.putBoolean(mDefaultAccountSavedKey, true); - editor.commit(); + DialerStrictMode.bypass(editor::commit); } public void registerChangeListener(ChangeListener listener) { diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java index 99a16d931..a5d650215 100644 --- a/java/com/android/dialer/app/DialtactsActivity.java +++ b/java/com/android/dialer/app/DialtactsActivity.java @@ -31,6 +31,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.os.Trace; +import android.preference.PreferenceManager; import android.provider.CallLog.Calls; import android.speech.RecognizerIntent; import android.support.annotation.MainThread; @@ -120,6 +121,7 @@ import com.android.dialer.simulator.Simulator; import com.android.dialer.simulator.SimulatorComponent; import com.android.dialer.smartdial.SmartDialNameMatcher; import com.android.dialer.smartdial.SmartDialPrefix; +import com.android.dialer.strictmode.DialerStrictMode; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.PermissionsUtil; @@ -387,6 +389,8 @@ public class DialtactsActivity extends TransactionSafeActivity Trace.beginSection(TAG + " onCreate"); super.onCreate(savedInstanceState); + warmupSharedPrefs(); + mFirstLaunch = true; isLastTabEnabled = ConfigProviderBindings.get(this).getBoolean("last_tab_enabled", false); @@ -503,6 +507,32 @@ public class DialtactsActivity extends TransactionSafeActivity Trace.endSection(); } + /** + * We frequently access shared preferences on the main thread, which causes strict mode + * violations. Warm up the shared preferences here so that later uses of shared preferences access + * the in-memory versions and we don't have to bypass strict mode at every point in the + * application where shared preferences are accessed. + */ + private void warmupSharedPrefs() { + DialerStrictMode.bypass( + () -> { + // From credential-encrypted (CE) storage, i.e.: + // /data/data/com.google.android.dialer/shared_prefs + + // com.google.android.dialer_preferences.xml + PreferenceManager.getDefaultSharedPreferences(this); + + // com.google.android.dialer.xml + getSharedPreferences(getPackageName(), Context.MODE_PRIVATE); + + // From device-encrypted (DE) storage, i.e.: + // /data/user_de/0/com.android.dialer/shared_prefs/ + + // com.google.android.dialer_preferences.xml + DialerUtils.getDefaultSharedPreferenceForDeviceProtectedStorageContext(this); + }); + } + @NonNull private ActionBar getActionBarSafely() { return Assert.isNotNull(getSupportActionBar()); @@ -855,7 +885,7 @@ public class DialtactsActivity extends TransactionSafeActivity Assert.isNotNull(mListsFragment.getView()).animate().alpha(0).withLayer(); - //adjust the title, so the user will know where we're at when the activity start/resumes. + // adjust the title, so the user will know where we're at when the activity start/resumes. setTitle(R.string.launcherDialpadActivityLabel); } @@ -917,7 +947,7 @@ public class DialtactsActivity extends TransactionSafeActivity exitSearchUi(); } } - //reset the title to normal. + // reset the title to normal. setTitle(R.string.launcherActivityLabel); } diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java index 6a7c588d9..c4adb37ef 100644 --- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java +++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java @@ -24,6 +24,7 @@ import com.android.dialer.enrichedcall.stub.StubEnrichedCallModule; import com.android.dialer.inject.ContextModule; import com.android.dialer.lightbringer.stub.StubLightbringerModule; import com.android.dialer.simulator.impl.SimulatorModule; +import com.android.dialer.storage.StorageModule; import com.android.incallui.calllocation.stub.StubCallLocationModule; import com.android.incallui.maps.stub.StubMapsModule; import com.android.voicemail.impl.VoicemailModule; @@ -39,6 +40,7 @@ import javax.inject.Singleton; DialerExecutorModule.class, SharedPrefConfigProviderModule.class, SimulatorModule.class, + StorageModule.class, StubCallLocationModule.class, StubEnrichedCallModule.class, StubMapsModule.class, diff --git a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java index 8ac071f77..1349564c8 100644 --- a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java +++ b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java @@ -24,6 +24,7 @@ import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.lightbringer.LightbringerComponent; import com.android.dialer.main.MainComponent; import com.android.dialer.simulator.SimulatorComponent; +import com.android.dialer.storage.StorageComponent; import com.android.incallui.calllocation.CallLocationComponent; import com.android.incallui.maps.MapsComponent; import com.android.voicemail.VoicemailComponent; @@ -42,5 +43,6 @@ public interface BaseDialerRootComponent EnrichedCallComponent.HasComponent, MapsComponent.HasComponent, SimulatorComponent.HasComponent, + StorageComponent.HasComponent, VoicemailComponent.HasComponent, LightbringerComponent.HasComponent {} diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java index 2b4de974b..570b5695c 100644 --- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java +++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java @@ -24,6 +24,7 @@ import com.android.dialer.enrichedcall.stub.StubEnrichedCallModule; import com.android.dialer.inject.ContextModule; import com.android.dialer.lightbringer.stub.StubLightbringerModule; import com.android.dialer.simulator.impl.SimulatorModule; +import com.android.dialer.storage.StorageModule; import com.android.incallui.calllocation.impl.CallLocationModule; import com.android.incallui.maps.impl.MapsModule; import com.android.voicemail.impl.VoicemailModule; @@ -43,6 +44,7 @@ import javax.inject.Singleton; DialerExecutorModule.class, SharedPrefConfigProviderModule.class, SimulatorModule.class, + StorageModule.class, StubEnrichedCallModule.class, MapsModule.class, VoicemailModule.class, diff --git a/java/com/android/dialer/blocking/FilteredNumberCompat.java b/java/com/android/dialer/blocking/FilteredNumberCompat.java index e104c4f94..548c965ad 100644 --- a/java/com/android/dialer/blocking/FilteredNumberCompat.java +++ b/java/com/android/dialer/blocking/FilteredNumberCompat.java @@ -38,6 +38,7 @@ import com.android.dialer.database.FilteredNumberContract.FilteredNumber; import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns; import com.android.dialer.database.FilteredNumberContract.FilteredNumberSources; import com.android.dialer.database.FilteredNumberContract.FilteredNumberTypes; +import com.android.dialer.strictmode.DialerStrictMode; import com.android.dialer.telecom.TelecomUtil; import java.util.ArrayList; import java.util.List; @@ -124,8 +125,10 @@ public class FilteredNumberCompat { * android.provider.BlockedNumberContract} blocking, {@code false} otherwise. */ public static boolean hasMigratedToNewBlocking(Context context) { - return PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(HAS_MIGRATED_TO_NEW_BLOCKING_KEY, false); + return DialerStrictMode.bypass( + () -> + PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(HAS_MIGRATED_TO_NEW_BLOCKING_KEY, false)); } /** diff --git a/java/com/android/dialer/storage/DeviceProtected.java b/java/com/android/dialer/storage/DeviceProtected.java new file mode 100644 index 000000000..862259a61 --- /dev/null +++ b/java/com/android/dialer/storage/DeviceProtected.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.dialer.storage; + +import javax.inject.Qualifier; + +/** Annotation for retrieving device protected storage objects. */ +@Qualifier +public @interface DeviceProtected {} diff --git a/java/com/android/dialer/storage/StorageComponent.java b/java/com/android/dialer/storage/StorageComponent.java new file mode 100644 index 000000000..51afea70b --- /dev/null +++ b/java/com/android/dialer/storage/StorageComponent.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.storage; + +import android.content.Context; +import android.content.SharedPreferences; +import com.android.dialer.inject.HasRootComponent; +import dagger.Subcomponent; + +/** Dagger component for storage. */ +@Subcomponent +public abstract class StorageComponent { + + public abstract @DeviceProtected SharedPreferences deviceProtectedSharedPreferences(); + + public static StorageComponent get(Context context) { + return ((StorageComponent.HasComponent) + ((HasRootComponent) context.getApplicationContext()).component()) + .storageComponent(); + } + + /** Used to refer to the root application component. */ + public interface HasComponent { + StorageComponent storageComponent(); + } +} diff --git a/java/com/android/dialer/storage/StorageModule.java b/java/com/android/dialer/storage/StorageModule.java new file mode 100644 index 000000000..8c97980c1 --- /dev/null +++ b/java/com/android/dialer/storage/StorageModule.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.dialer.storage; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.support.v4.content.ContextCompat; +import com.android.dialer.inject.ApplicationContext; +import dagger.Module; +import dagger.Provides; +import javax.inject.Singleton; + +/** Module for the storage component. */ +@Module +public class StorageModule { + + @Provides + @Singleton + @DeviceProtected + static SharedPreferences provideDeviceProtectedSharedPreferences( + @ApplicationContext Context appContext) { + // #createDeviceProtectedStorageContext returns a new context each time, so we cache the shared + // preferences object in order to avoid accessing disk for every operation. + Context deviceProtectedContext = ContextCompat.createDeviceProtectedStorageContext(appContext); + + // ContextCompat.createDeviceProtectedStorageContext(context) returns null on pre-N, thus fall + // back to regular default shared preference for pre-N devices since devices protected context + // is not available. + return PreferenceManager.getDefaultSharedPreferences( + deviceProtectedContext != null ? deviceProtectedContext : appContext); + } +} diff --git a/java/com/android/dialer/strictmode/DialerStrictMode.java b/java/com/android/dialer/strictmode/DialerStrictMode.java index 3c31aa954..ad1a6c60d 100644 --- a/java/com/android/dialer/strictmode/DialerStrictMode.java +++ b/java/com/android/dialer/strictmode/DialerStrictMode.java @@ -103,4 +103,22 @@ public final class DialerStrictMode { enableDeathPenalty(); } } + + /** + * Convenience method for disabling and enabling the death penalty using lambdas. + * + * <p>For example: + * + * <p><code> + * DialerStrictMode.bypass(() -> doDiskAccessOnMainThread()); + * </code> + */ + public static void bypass(Runnable runnable) { + disableDeathPenalty(); + try { + runnable.run(); + } finally { + enableDeathPenalty(); + } + } } diff --git a/java/com/android/dialer/util/DialerUtils.java b/java/com/android/dialer/util/DialerUtils.java index 63f870e73..f38c650d3 100644 --- a/java/com/android/dialer/util/DialerUtils.java +++ b/java/com/android/dialer/util/DialerUtils.java @@ -38,6 +38,7 @@ import android.view.inputmethod.InputMethodManager; import android.widget.Toast; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; +import com.android.dialer.storage.StorageComponent; import com.android.dialer.telecom.TelecomUtil; import java.io.File; import java.util.Iterator; @@ -233,14 +234,9 @@ public class DialerUtils { public static SharedPreferences getDefaultSharedPreferenceForDeviceProtectedStorageContext( @NonNull Context context) { Assert.isNotNull(context); - Context deviceProtectedContext = - ContextCompat.isDeviceProtectedStorage(context) - ? context - : ContextCompat.createDeviceProtectedStorageContext(context); - // ContextCompat.createDeviceProtectedStorageContext(context) returns null on pre-N, thus fall - // back to regular default shared preference for pre-N devices since devices protected context - // is not available. - return PreferenceManager.getDefaultSharedPreferences( - deviceProtectedContext != null ? deviceProtectedContext : context); + if (ContextCompat.isDeviceProtectedStorage(context)) { + return PreferenceManager.getDefaultSharedPreferences(context); + } + return StorageComponent.get(context.getApplicationContext()).deviceProtectedSharedPreferences(); } } diff --git a/java/com/android/dialer/util/IntentUtil.java b/java/com/android/dialer/util/IntentUtil.java index 2f265b5a7..f45396635 100644 --- a/java/com/android/dialer/util/IntentUtil.java +++ b/java/com/android/dialer/util/IntentUtil.java @@ -31,7 +31,8 @@ public class IntentUtil { } public static Intent getNewContactIntent() { - return new Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI); + return new Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI) + .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } public static Intent getNewContactIntent(CharSequence phoneNumber) { diff --git a/java/com/android/incallui/CallerInfoAsyncQuery.java b/java/com/android/incallui/CallerInfoAsyncQuery.java index d620d4705..858d0f4b7 100644 --- a/java/com/android/incallui/CallerInfoAsyncQuery.java +++ b/java/com/android/incallui/CallerInfoAsyncQuery.java @@ -41,6 +41,7 @@ import com.android.dialer.phonenumbercache.CachedNumberLookupService; import com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo; import com.android.dialer.phonenumbercache.ContactInfoHelper; import com.android.dialer.phonenumbercache.PhoneNumberCache; +import com.android.dialer.strictmode.DialerStrictMode; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -189,7 +190,7 @@ public class CallerInfoAsyncQuery { CallerInfo info, OnQueryCompleteListener listener, Object cookie) { - long[] directoryIds = getDirectoryIds(context); + long[] directoryIds = DialerStrictMode.bypass(() -> getDirectoryIds(context)); int size = directoryIds.length; if (size == 0) { return false; diff --git a/java/com/android/incallui/incall/impl/InCallFragment.java b/java/com/android/incallui/incall/impl/InCallFragment.java index 1730c808c..7e39ceb40 100644 --- a/java/com/android/incallui/incall/impl/InCallFragment.java +++ b/java/com/android/incallui/incall/impl/InCallFragment.java @@ -44,6 +44,7 @@ import com.android.dialer.common.LogUtil; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; import com.android.dialer.multimedia.MultimediaData; +import com.android.dialer.strictmode.DialerStrictMode; import com.android.dialer.widget.LockableViewPager; import com.android.incallui.audioroute.AudioRouteSelectorDialogFragment; import com.android.incallui.audioroute.AudioRouteSelectorDialogFragment.AudioRouteSelectorPresenter; @@ -139,7 +140,10 @@ public class InCallFragment extends Fragment @Nullable ViewGroup viewGroup, @Nullable Bundle bundle) { LogUtil.i("InCallFragment.onCreateView", null); - final View view = layoutInflater.inflate(R.layout.frag_incall_voice, viewGroup, false); + // Bypass to avoid StrictModeResourceMismatchViolation + final View view = + DialerStrictMode.bypass( + () -> layoutInflater.inflate(R.layout.frag_incall_voice, viewGroup, false)); contactGridManager = new ContactGridManager( view, diff --git a/java/com/android/voicemail/impl/VoicemailStatus.java b/java/com/android/voicemail/impl/VoicemailStatus.java index ec1ab4e70..5553cf5e0 100644 --- a/java/com/android/voicemail/impl/VoicemailStatus.java +++ b/java/com/android/voicemail/impl/VoicemailStatus.java @@ -24,6 +24,7 @@ import android.provider.VoicemailContract; import android.provider.VoicemailContract.Status; import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; +import com.android.dialer.strictmode.DialerStrictMode; public class VoicemailStatus { @@ -99,7 +100,7 @@ public class VoicemailStatus { ContentResolver contentResolver = mContext.getContentResolver(); Uri statusUri = VoicemailContract.Status.buildSourceUri(mContext.getPackageName()); try { - contentResolver.insert(statusUri, mValues); + DialerStrictMode.bypass(() -> contentResolver.insert(statusUri, mValues)); } catch (IllegalArgumentException iae) { VvmLog.e(TAG, "apply :: failed to insert content resolver ", iae); mValues.clear(); diff --git a/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java b/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java index 18b2b9274..1624ce579 100644 --- a/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java +++ b/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java @@ -35,6 +35,7 @@ import android.telecom.TelecomManager; import android.text.TextUtils; import com.android.dialer.common.Assert; import com.android.dialer.common.concurrent.ThreadUtil; +import com.android.dialer.strictmode.DialerStrictMode; import com.android.voicemail.VoicemailComponent; /** @@ -126,8 +127,10 @@ public class ConfigOverrideFragment extends PreferenceFragment } public static boolean isOverridden(Context context) { - return PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(context.getString(R.string.vvm_config_override_enabled_key), false); + return DialerStrictMode.bypass( + () -> + PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(context.getString(R.string.vvm_config_override_enabled_key), false)); } public static PersistableBundle getConfig(Context context) { diff --git a/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java b/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java index 107234edc..baf58041f 100644 --- a/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java +++ b/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java @@ -30,6 +30,7 @@ import android.os.Parcelable; import android.preference.PreferenceManager; import android.support.annotation.MainThread; import com.android.dialer.constants.ScheduledJobIds; +import com.android.dialer.strictmode.DialerStrictMode; import com.android.voicemail.impl.Assert; import com.android.voicemail.impl.VvmLog; import java.util.ArrayList; @@ -58,7 +59,8 @@ public class TaskSchedulerJobService extends JobService implements TaskExecutor. public boolean onStartJob(JobParameters params) { int jobId = params.getTransientExtras().getInt(EXTRA_JOB_ID); int expectedJobId = - PreferenceManager.getDefaultSharedPreferences(this).getInt(EXPECTED_JOB_ID, 0); + DialerStrictMode.bypass( + () -> PreferenceManager.getDefaultSharedPreferences(this).getInt(EXPECTED_JOB_ID, 0)); if (jobId != expectedJobId) { VvmLog.e( TAG, "Job " + jobId + " is not the last scheduled job " + expectedJobId + ", ignoring"); |