BridgePackageManager.java revision efe0830e745db4879e4230cff5ce89dd465eadf5
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.layoutlib.bridge.android;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.app.PackageInstallObserver;
22import android.content.ComponentName;
23import android.content.Intent;
24import android.content.IntentFilter;
25import android.content.IntentSender;
26import android.content.pm.ActivityInfo;
27import android.content.pm.ApplicationInfo;
28import android.content.pm.ChangedPackages;
29import android.content.pm.InstantAppInfo;
30import android.content.pm.FeatureInfo;
31import android.content.pm.IPackageDataObserver;
32import android.content.pm.IPackageDeleteObserver;
33import android.content.pm.IPackageInstallObserver;
34import android.content.pm.IPackageStatsObserver;
35import android.content.pm.InstrumentationInfo;
36import android.content.pm.IntentFilterVerificationInfo;
37import android.content.pm.KeySet;
38import android.content.pm.PackageInfo;
39import android.content.pm.PackageInstaller;
40import android.content.pm.PackageItemInfo;
41import android.content.pm.PackageManager;
42import android.content.pm.PermissionGroupInfo;
43import android.content.pm.PermissionInfo;
44import android.content.pm.ProviderInfo;
45import android.content.pm.ResolveInfo;
46import android.content.pm.ServiceInfo;
47import android.content.pm.SharedLibraryInfo;
48import android.content.pm.VerifierDeviceIdentity;
49import android.content.pm.VersionedPackage;
50import android.content.res.Resources;
51import android.content.res.XmlResourceParser;
52import android.graphics.Rect;
53import android.graphics.drawable.ColorDrawable;
54import android.graphics.drawable.Drawable;
55import android.net.Uri;
56import android.os.Handler;
57import android.os.UserHandle;
58import android.os.storage.VolumeInfo;
59import java.util.List;
60
61/**
62 * An implementation of {@link PackageManager} that does nothing.
63 */
64@SuppressWarnings("deprecation")
65public class BridgePackageManager extends PackageManager {
66    @Override
67    public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException {
68        return null;
69    }
70
71    @Override
72    public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
73            throws NameNotFoundException {
74        return null;
75    }
76
77    @Override
78    public PackageInfo getPackageInfo(VersionedPackage versionedPackage,
79            @PackageInfoFlags int flags) throws NameNotFoundException {
80        return null;
81    }
82
83    @Override
84    public List<SharedLibraryInfo> getSharedLibraries(@InstallFlags int flags) {
85        return null;
86    }
87
88    @Override
89    public List<SharedLibraryInfo> getSharedLibrariesAsUser(@InstallFlags int flags,
90            int userId) {
91        return null;
92    }
93
94    @Override
95    public String[] currentToCanonicalPackageNames(String[] names) {
96        return new String[0];
97    }
98
99    @Override
100    public String[] canonicalToCurrentPackageNames(String[] names) {
101        return new String[0];
102    }
103
104    @Override
105    public Intent getLaunchIntentForPackage(String packageName) {
106        return null;
107    }
108
109    @Override
110    public Intent getLeanbackLaunchIntentForPackage(String packageName) {
111        return null;
112    }
113
114    @Override
115    public int[] getPackageGids(String packageName) throws NameNotFoundException {
116        return new int[0];
117    }
118
119    @Override
120    public int[] getPackageGids(String packageName, int flags) throws NameNotFoundException {
121        return new int[0];
122    }
123
124    @Override
125    public int getPackageUid(String packageName, int flags) throws NameNotFoundException {
126        return 0;
127    }
128
129    @Override
130    public int getPackageUidAsUser(String packageName, int userHandle) throws NameNotFoundException {
131        return 0;
132    }
133
134    @Override
135    public int getPackageUidAsUser(String packageName, int flags, int userHandle) throws NameNotFoundException {
136        return 0;
137    }
138
139    @Override
140    public PermissionInfo getPermissionInfo(String name, int flags) throws NameNotFoundException {
141        return null;
142    }
143
144    @Override
145    public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
146            throws NameNotFoundException {
147        return null;
148    }
149
150    @Override
151    public boolean isPermissionReviewModeEnabled() {
152        return false;
153    }
154
155    @Override
156    public PermissionGroupInfo getPermissionGroupInfo(String name, int flags)
157            throws NameNotFoundException {
158        return null;
159    }
160
161    @Override
162    public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
163        return null;
164    }
165
166    @Override
167    public ApplicationInfo getApplicationInfo(String packageName, int flags)
168            throws NameNotFoundException {
169        return null;
170    }
171
172    @Override
173    public ApplicationInfo getApplicationInfoAsUser(String packageName, int flags, int userId)
174            throws NameNotFoundException {
175        return null;
176    }
177
178    @Override
179    public ActivityInfo getActivityInfo(ComponentName component, int flags)
180            throws NameNotFoundException {
181        return null;
182    }
183
184    @Override
185    public ActivityInfo getReceiverInfo(ComponentName component, int flags)
186            throws NameNotFoundException {
187        return null;
188    }
189
190    @Override
191    public ServiceInfo getServiceInfo(ComponentName component, int flags)
192            throws NameNotFoundException {
193        return null;
194    }
195
196    @Override
197    public ProviderInfo getProviderInfo(ComponentName component, int flags)
198            throws NameNotFoundException {
199        return null;
200    }
201
202    @Override
203    public List<PackageInfo> getInstalledPackages(int flags) {
204        return null;
205    }
206
207    @Override
208    public List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) {
209        return null;
210    }
211
212    @Override
213    public List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
214        return null;
215    }
216
217    @Override
218    public int checkPermission(String permName, String pkgName) {
219        return 0;
220    }
221
222    @Override
223    public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
224        return false;
225    }
226
227    @Override
228    public String getPermissionControllerPackageName() {
229        return null;
230    }
231
232    @Override
233    public boolean addPermission(PermissionInfo info) {
234        return false;
235    }
236
237    @Override
238    public boolean addPermissionAsync(PermissionInfo info) {
239        return false;
240    }
241
242    @Override
243    public void removePermission(String name) {
244    }
245
246    @Override
247    public void grantRuntimePermission(String packageName, String permissionName, UserHandle user) {
248    }
249
250    @Override
251    public void revokeRuntimePermission(String packageName, String permissionName,
252            UserHandle user) {
253    }
254
255    @Override
256    public int getPermissionFlags(String permissionName, String packageName, UserHandle user) {
257        return 0;
258    }
259
260    @Override
261    public void updatePermissionFlags(String permissionName, String packageName, int flagMask,
262            int flagValues, UserHandle user) {
263    }
264
265    @Override
266    public boolean shouldShowRequestPermissionRationale(String permission) {
267        return false;
268    }
269
270    @Override
271    public int checkSignatures(String pkg1, String pkg2) {
272        return 0;
273    }
274
275    @Override
276    public int checkSignatures(int uid1, int uid2) {
277        return 0;
278    }
279
280    @Override
281    public String[] getPackagesForUid(int uid) {
282        return new String[0];
283    }
284
285    @Override
286    public String getNameForUid(int uid) {
287        return null;
288    }
289
290    @Override
291    public String[] getNamesForUids(int[] uids) {
292        return null;
293    }
294
295    @Override
296    public int getUidForSharedUser(String sharedUserName) throws NameNotFoundException {
297        return 0;
298    }
299
300    @Override
301    public List<ApplicationInfo> getInstalledApplications(int flags) {
302        return null;
303    }
304
305    @Override
306    public List<ApplicationInfo> getInstalledApplicationsAsUser(int flags, int userId) {
307        return null;
308    }
309
310    @Override
311    public List<InstantAppInfo> getInstantApps() {
312        return null;
313    }
314
315    @Override
316    public Drawable getInstantAppIcon(String packageName) {
317        assert false : "Unsupported operation";
318        return new ColorDrawable();
319    }
320
321    @Override
322    public byte[] getInstantAppCookie() {
323        return new byte[0];
324    }
325
326    @Override
327    public boolean isInstantApp() {
328        return false;
329    }
330
331    @Override
332    public boolean isInstantApp(String packageName) {
333        return false;
334    }
335
336    @Override
337    public int getInstantAppCookieMaxBytes() {
338        return 0;
339    }
340
341    @Override
342    public int getInstantAppCookieMaxSize() {
343        return 0;
344    }
345
346    @Override
347    public void clearInstantAppCookie() {;
348
349    }
350
351    @Override
352    public void updateInstantAppCookie(@Nullable byte[] cookie) {
353
354    }
355
356    @Override
357    public boolean setInstantAppCookie(@NonNull byte[] cookie) {
358        return false;
359    }
360
361    @Override
362    public String[] getSystemSharedLibraryNames() {
363        return new String[0];
364    }
365
366    @Override
367    public String getServicesSystemSharedLibraryPackageName() {
368        return null;
369    }
370
371    @Override
372    public @NonNull String getSharedSystemSharedLibraryPackageName() {
373        return null;
374    }
375
376    @Override
377    public FeatureInfo[] getSystemAvailableFeatures() {
378        return new FeatureInfo[0];
379    }
380
381    @Override
382    public boolean hasSystemFeature(String name) {
383        return false;
384    }
385
386    @Override
387    public boolean hasSystemFeature(String name, int version) {
388        return false;
389    }
390
391    @Override
392    public ResolveInfo resolveActivity(Intent intent, int flags) {
393        return null;
394    }
395
396    @Override
397    public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
398        return null;
399    }
400
401    @Override
402    public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
403        return null;
404    }
405
406    @Override
407    public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
408        return null;
409    }
410
411    @Override
412    public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller, Intent[] specifics,
413            Intent intent, int flags) {
414        return null;
415    }
416
417    @Override
418    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
419        return null;
420    }
421
422    @Override
423    public List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) {
424        return null;
425    }
426
427    @Override
428    public ResolveInfo resolveService(Intent intent, int flags) {
429        return null;
430    }
431
432    @Override
433    public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
434        return null;
435    }
436
437    @Override
438    public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
439        return null;
440    }
441
442    @Override
443    public List<ResolveInfo> queryIntentContentProvidersAsUser(Intent intent, int flags,
444            int userId) {
445        return null;
446    }
447
448    @Override
449    public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
450        return null;
451    }
452
453    @Override
454    public ProviderInfo resolveContentProvider(String name, int flags) {
455        return null;
456    }
457
458    @Override
459    public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) {
460        return null;
461    }
462
463    @Override
464    public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
465        return null;
466    }
467
468    @Override
469    public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags)
470            throws NameNotFoundException {
471        return null;
472    }
473
474    @Override
475    public List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) {
476        return null;
477    }
478
479    @Override
480    public Drawable getDrawable(String packageName, int resid, ApplicationInfo appInfo) {
481        return null;
482    }
483
484    @Override
485    public Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException {
486        return null;
487    }
488
489    @Override
490    public Drawable getActivityIcon(Intent intent) throws NameNotFoundException {
491        return null;
492    }
493
494    @Override
495    public Drawable getActivityBanner(ComponentName activityName) throws NameNotFoundException {
496        return null;
497    }
498
499    @Override
500    public Drawable getActivityBanner(Intent intent) throws NameNotFoundException {
501        return null;
502    }
503
504    @Override
505    public Drawable getDefaultActivityIcon() {
506        return null;
507    }
508
509    @Override
510    public Drawable getApplicationIcon(ApplicationInfo info) {
511        return null;
512    }
513
514    @Override
515    public Drawable getApplicationIcon(String packageName) throws NameNotFoundException {
516        return null;
517    }
518
519    @Override
520    public Drawable getApplicationBanner(ApplicationInfo info) {
521        return null;
522    }
523
524    @Override
525    public Drawable getApplicationBanner(String packageName) throws NameNotFoundException {
526        return null;
527    }
528
529    @Override
530    public Drawable getActivityLogo(ComponentName activityName) throws NameNotFoundException {
531        return null;
532    }
533
534    @Override
535    public Drawable getActivityLogo(Intent intent) throws NameNotFoundException {
536        return null;
537    }
538
539    @Override
540    public Drawable getApplicationLogo(ApplicationInfo info) {
541        return null;
542    }
543
544    @Override
545    public Drawable getApplicationLogo(String packageName) throws NameNotFoundException {
546        return null;
547    }
548
549    @Override
550    public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
551        return null;
552    }
553
554    @Override
555    public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
556            Rect badgeLocation, int badgeDensity) {
557        return null;
558    }
559
560    @Override
561    public Drawable getUserBadgeForDensity(UserHandle user, int density) {
562        return null;
563    }
564
565    @Override
566    public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
567        return null;
568    }
569
570    @Override
571    public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
572        return null;
573    }
574
575    @Override
576    public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) {
577        return null;
578    }
579
580    @Override
581    public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) {
582        return null;
583    }
584
585    @Override
586    public CharSequence getApplicationLabel(ApplicationInfo info) {
587        return null;
588    }
589
590    @Override
591    public Resources getResourcesForActivity(ComponentName activityName)
592            throws NameNotFoundException {
593        return null;
594    }
595
596    @Override
597    public Resources getResourcesForApplication(ApplicationInfo app) throws NameNotFoundException {
598        return null;
599    }
600
601    @Override
602    public Resources getResourcesForApplication(String appPackageName)
603            throws NameNotFoundException {
604        return null;
605    }
606
607    @Override
608    public Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
609            throws NameNotFoundException {
610        return null;
611    }
612
613    @Override
614    public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
615            String installerPackageName) {
616    }
617
618    @Override
619    public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags,
620            String installerPackageName) {
621    }
622
623    @Override
624    public int installExistingPackage(String packageName) throws NameNotFoundException {
625        return 0;
626    }
627
628    @Override
629    public int installExistingPackage(String packageName, int installReason)
630            throws NameNotFoundException {
631        return 0;
632    }
633
634    @Override
635    public int installExistingPackageAsUser(String packageName, int userId)
636            throws NameNotFoundException {
637        return 0;
638    }
639
640    @Override
641    public void verifyPendingInstall(int id, int verificationCode) {
642    }
643
644    @Override
645    public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
646            long millisecondsToDelay) {
647    }
648
649    @Override
650    public void verifyIntentFilter(int verificationId, int verificationCode,
651            List<String> outFailedDomains) {
652    }
653
654    @Override
655    public int getIntentVerificationStatusAsUser(String packageName, int userId) {
656        return 0;
657    }
658
659    @Override
660    public boolean updateIntentVerificationStatusAsUser(String packageName, int status, int userId) {
661        return false;
662    }
663
664    @Override
665    public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
666        return null;
667    }
668
669    @Override
670    public List<IntentFilter> getAllIntentFilters(String packageName) {
671        return null;
672    }
673
674    @Override
675    public String getDefaultBrowserPackageNameAsUser(int userId) {
676        return null;
677    }
678
679    @Override
680    public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
681        return false;
682    }
683
684    @Override
685    public void setInstallerPackageName(String targetPackage, String installerPackageName) {
686    }
687
688    @Override
689    public void setUpdateAvailable(String packageName, boolean updateAvailable) {
690    }
691
692    @Override
693    public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
694    }
695
696    @Override
697    public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags,
698            int userId) {
699    }
700
701    @Override
702    public String getInstallerPackageName(String packageName) {
703        return null;
704    }
705
706    @Override
707    public void clearApplicationUserData(String packageName, IPackageDataObserver observer) {
708    }
709
710    @Override
711    public void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) {
712    }
713
714    @Override
715    public void deleteApplicationCacheFilesAsUser(String packageName, int userId,
716            IPackageDataObserver observer) {
717    }
718
719    @Override
720    public void freeStorageAndNotify(String volumeUuid, long freeStorageSize,
721            IPackageDataObserver observer) {
722    }
723
724    @Override
725    public void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {
726    }
727
728    @Override
729    public void getPackageSizeInfoAsUser(String packageName, int userHandle,
730            IPackageStatsObserver observer) {
731    }
732
733    @Override
734    public void addPackageToPreferred(String packageName) {
735    }
736
737    @Override
738    public void removePackageFromPreferred(String packageName) {
739    }
740
741    @Override
742    public List<PackageInfo> getPreferredPackages(int flags) {
743        return null;
744    }
745
746    @Override
747    public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set,
748            ComponentName activity) {
749    }
750
751    @Override
752    public void replacePreferredActivity(IntentFilter filter, int match, ComponentName[] set,
753            ComponentName activity) {
754    }
755
756    @Override
757    public void clearPackagePreferredActivities(String packageName) {
758    }
759
760    @Override
761    public int getPreferredActivities(List<IntentFilter> outFilters,
762            List<ComponentName> outActivities, String packageName) {
763        return 0;
764    }
765
766    @Override
767    public ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
768        return null;
769    }
770
771    @Override
772    public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) {
773    }
774
775    @Override
776    public int getComponentEnabledSetting(ComponentName componentName) {
777        return 0;
778    }
779
780    @Override
781    public void setApplicationEnabledSetting(String packageName, int newState, int flags) {
782    }
783
784    @Override
785    public int getApplicationEnabledSetting(String packageName) {
786        return 0;
787    }
788
789    @Override
790    public void flushPackageRestrictionsAsUser(int userId) {
791    }
792
793    @Override
794    public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
795            UserHandle userHandle) {
796        return false;
797    }
798
799    @Override
800    public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle userHandle) {
801        return false;
802    }
803
804    @Override
805    public boolean isSafeMode() {
806        return false;
807    }
808
809    @Override
810    public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
811    }
812
813    @Override
814    public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
815    }
816
817    @Override
818    public KeySet getKeySetByAlias(String packageName, String alias) {
819        return null;
820    }
821
822    @Override
823    public KeySet getSigningKeySet(String packageName) {
824        return null;
825    }
826
827    @Override
828    public boolean isSignedBy(String packageName, KeySet ks) {
829        return false;
830    }
831
832    @Override
833    public boolean isSignedByExactly(String packageName, KeySet ks) {
834        return false;
835    }
836
837    @Override
838    public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
839            int userId) {
840        return new String[]{};
841    }
842
843    @Override
844    public boolean isPackageSuspendedForUser(String packageName, int userId) {
845        return false;
846    }
847
848    @Override
849    public void setApplicationCategoryHint(String packageName, int categoryHint) {
850    }
851
852    @Override
853    public int getMoveStatus(int moveId) {
854        return 0;
855    }
856
857    @Override
858    public void registerMoveCallback(MoveCallback callback, Handler handler) {
859    }
860
861    @Override
862    public void unregisterMoveCallback(MoveCallback callback) {
863    }
864
865    @Override
866    public int movePackage(String packageName, VolumeInfo vol) {
867        return 0;
868    }
869
870    @Override
871    public VolumeInfo getPackageCurrentVolume(ApplicationInfo app) {
872        return null;
873    }
874
875    @Override
876    public List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) {
877        return null;
878    }
879
880    @Override
881    public int movePrimaryStorage(VolumeInfo vol) {
882        return 0;
883    }
884
885    @Override
886    public VolumeInfo getPrimaryStorageCurrentVolume() {
887        return null;
888    }
889
890    @Override
891    public List<VolumeInfo> getPrimaryStorageCandidateVolumes() {
892        return null;
893    }
894
895    @Override
896    public VerifierDeviceIdentity getVerifierDeviceIdentity() {
897        return null;
898    }
899
900    @Override
901    public ChangedPackages getChangedPackages(int sequenceNumber) {
902        return null;
903    }
904
905    @Override
906    public boolean isUpgrade() {
907        return false;
908    }
909
910    @Override
911    public PackageInstaller getPackageInstaller() {
912        return null;
913    }
914
915    @Override
916    public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId,
917            int flags) {
918    }
919
920    @Override
921    public void clearCrossProfileIntentFilters(int sourceUserId) {
922    }
923
924    @Override
925    public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
926        return null;
927    }
928
929    @Override
930    public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
931        return null;
932    }
933
934    @Override
935    public boolean isPackageAvailable(String packageName) {
936        return false;
937    }
938
939    @Override
940    public int getInstallReason(String packageName, UserHandle user) {
941        return INSTALL_REASON_UNKNOWN;
942    }
943
944    @Override
945    public boolean canRequestPackageInstalls() {
946        return false;
947    }
948
949    @Override
950    public ComponentName getInstantAppResolverSettingsComponent() {
951        return null;
952    }
953
954    @Override
955    public ComponentName getInstantAppInstallerComponent() {
956        return null;
957    }
958
959    @Override
960    public String getInstantAppAndroidId(String packageName, UserHandle user) {
961        return null;
962    }
963
964    @Override
965    public void registerDexModule(String dexModulePath,
966            @Nullable DexModuleRegisterCallback callback) {
967        callback.onDexModuleRegistered(dexModulePath, false, null);
968    }
969}
970