Android apk 包管理(PackageManagerService)安裝管理_第1頁
Android apk 包管理(PackageManagerService)安裝管理_第2頁
Android apk 包管理(PackageManagerService)安裝管理_第3頁
Android apk 包管理(PackageManagerService)安裝管理_第4頁
Android apk 包管理(PackageManagerService)安裝管理_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Androidapk安裝管理(PackageManagerService分析)本篇主要分析了系統(tǒng)啟動階段包管理服務(wù)的啟動流程,其中的幾個接口在apk安裝時也會被調(diào)用。包管理服務(wù)啟動時主要做的工作大致有如下幾方面:建立java層的installer與c層的installd的socket聯(lián)接,使得在上層的install,remove,dexopt等功能最終由installd在底層實現(xiàn)建立PackageHandler消息循環(huán),用于處理外部的apk安裝請求消息,女口adbinstall,packageinstaller安裝apk時會發(fā)送消息解析/system/etc/permission下xml文件(framework/base/data/etc/),包括platform.xml和系統(tǒng)支持的各種硬件模塊的feature.主要工作:建立底層userids和groupids同上層permissions之間的映射;可以指定一個權(quán)限與幾個組ID對應(yīng)。當一個APK被授予這個權(quán)限時,它也同時屬于這幾個組。給一些底層用戶分配權(quán)限,如給shell授予各種permission權(quán)限;把一個權(quán)限賦予一個UID,當進程使用這個UID運行時,就具備了這個權(quán)限。⑶library,系統(tǒng)增加的一些應(yīng)用需要link的擴展jar庫;⑷feature,系統(tǒng)每增加一個硬件,都要添加相應(yīng)的feature.將解析結(jié)果放入mSystemPermissions,mSharedLibraries,mSettings.mPermissions,mAvailableFeatures等幾個集合中供系統(tǒng)查詢和權(quán)限配置使用。4.檢查/data/system/packages.xml是否存在,這個文件是在解析apk時由writeLP()創(chuàng)建的,里面記錄了系統(tǒng)的permissions,以及每個apk的name,這些信息主要通過name,這些信息主要通過apk的AndroidManifest.xml解析獲取,解析完apk后將更新信息寫入這個文件并保存到flash,下次開機直接從里面讀取相關(guān)信息添加到內(nèi)存相關(guān)列表中。當有apk升級,安裝或刪除時會更新這個文件。檢查BootClassPath,mSharedLibraries及/system/framework下的jar是否需要dexopt,需要的則通過dexopt進行優(yōu)化啟動AppDirObserver線程監(jiān)測/system/framework,/system/app,/data/app,/data/app-private目錄的事件,主要監(jiān)聽add和remove事件。對于目錄監(jiān)聽底層通過inotify機制實現(xiàn),inotify是一種文件系統(tǒng)的變化通知機制,如文件增加、刪除等事件可以立刻讓用戶態(tài)得知,它為用戶態(tài)監(jiān)視文件系統(tǒng)的變化提供了強大的支持。當有addevent時調(diào)用scanPackageLI(File,int,int)處理;當有removeevent時調(diào)用removePackageLI()處理;對于以上幾個目錄下的apk逐個解析,主要是解析每個apk的AndroidManifest.xml文件,處理asset/res等資源文件,建立起每個apk的配置結(jié)構(gòu)信息,并將每個apk的配置信息添加到全局列表進行管理。調(diào)用installer.install()進行安裝工作,檢查apk里的dex文件是否需要再優(yōu)化,如果需要優(yōu)化則通過輔助工具dexopt進行優(yōu)化處理;將解析出的componet添加到pkg的對應(yīng)列表里;

對apk進行簽名和證書校驗,進行完整性驗證。8.將解析的每個apk的信息保存到packages.xml和packages.list文件里,packages.list記錄了如下數(shù)據(jù):pkgName,userid,debugFlag,dataPath(包的數(shù)據(jù)路徑)在Systemserver啟動 PackageManaggrService.main newPackageManagerDervice(),并添加到SepjviceMIanager~建立Installer與Installd的socket聯(lián)接創(chuàng)建PackageHandler消息處理循環(huán)詳細分析在systemserver.java中啟動包管理服務(wù)pm=PackageManagerService.main(context,factoryTest!=SystemServer.FACTORY_TEST_OFF);main函數(shù)主要功能是構(gòu)造PackageManagerService實例,然后添加到ServiceManager中。publicstaticfinalIPackageManagermain(Contextcontext,booleanfactoryTest){PackageManagerServicem=newPackageManagerService(context,factoryTest);ServiceManager.addService("package",m);returnm;}PackageManagerService(context,factoryTest)是包管理服務(wù)的主進程。它完成了對/system/app,/data/app,/system/framework,/data/app-private下的apk文件的解析。詳細流程如下:初始化過程:判斷ro.build.type是否等于eng;創(chuàng)建系統(tǒng)顯示像素實例mMetrics=newDisplayMetrics();倉U建mSettings實例mSettings=newSettings(),Settings類是PackageManagerService的一個靜態(tài)子類,它的作用主要是保持動態(tài)設(shè)置的信息,通過Settings()構(gòu)造函數(shù)在/data/system下倉U建了三個文件名:packages.xml,packages-backup.xml(這個文件在mSettings.writeLP()里被刪除了),packages.list。mSettings增加Iandroid.uid.system,android.uid.phone,android.uid.log三個共享用戶ID,同時授予其系統(tǒng)權(quán)限?!ńnstaller與installd的socket聯(lián)接Installerinstaller=newInstaller();installer.ping()&&Process.supportsProcesses();installd完成以下一些命令structcmdinfocmds[]={{"ping",0,do_ping},{"install",3,do_install},{"dexopt",3,do_dexopt},{"movedex",2,do_move_dex},{"rmdex",1,do_rm_dex},{"remove",1,do_remove},{"rename",2,do_rename},{"freecache",1,do_free_cache},{"rmcache",1,do_rm_cache},{"protect",2,do_protect},{"getsize",3,do_get_size}{"rmuserdata",1,do_rm_user_data}{"movefiles",0,do_movefiles},};〃獲取當前缺省的顯示像素WindowManagerwm=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);Displayd=wm.getDefaultDisplay();d.getMetrics(mMetrics);建立一個消息循環(huán),用于處理apk安裝時的請求消息處理(這些請求來自adbinstall/push,包安裝器,androidmarket下載安裝apk時發(fā)送的)mHandlerThread.start();mHandler=newPackageHandler(mHandlerThread.getLooper());這個消息循環(huán)處理的消息事件如下:staticfinalintSEND_PENDING_BROADCAST=1;staticfinalintMCS_BOUND=3;staticfinalintEND_COPY=4;staticfinalintINIT_COPY=5;staticfinalintMCS_UNBIND=6;staticfinalintSTART_CLEANING_PACKAGE=7;staticfinalintFIND_INSTALL_LOC=8;staticfinalintPOST_INSTALL=9;staticfinalintMCS_RECONNECT=10;staticfinalintMCS_GIVE_UP=11;staticfinalintUPDATED_MEDIA_STATUS=12;staticfinalintWRITE_SETTINGS=13;〃創(chuàng)建/data/data和/data/app-private目錄FiledataDir=Environment.getDataDirectory();//獲得/data目錄mAppDataDir=newFile(dataDir,"data");mDrmAppPrivateInstallDir=newFile(dataDir,"app-private");//Readpermissionsfrom/system/etc/permissiondirectory.〃這些文件在framework/base/data/etcVoidreadPermissions(){〃解析/system/etc/permission/下的*.xml文件,獲取權(quán)限信息〃最后解析該目錄下的platform.xml文件,使該文件里的權(quán)限在棧頂出現(xiàn),以便預先處理〃這個文件記錄了系統(tǒng)級應(yīng)用的uid及其擁有的權(quán)限File permFile = newFile(Environment.getRootDirectory(),"etc/permissions/platform.xml");readPermissionsFromXml(permFile);〃該函數(shù)的功能如下:通過xml解析器解釋*.xml文件,提取標簽名“group,"permission","assign-permission","library","feature"并進行相應(yīng)處理。在platform.xml中對底層的系統(tǒng)用戶和組ID(groupids)同上層的由平臺管理的permission名字之間進行了關(guān)系映射,使它們關(guān)聯(lián)起來。當一個應(yīng)用被授予某個權(quán)限后,同時屬于已知的組ID,這個應(yīng)用就可以進行允許這個組的文件系統(tǒng)操作,如(read,write,execute)。這里記錄了一些系統(tǒng)級的應(yīng)用的uid對應(yīng)的permission〃每個標簽的含義:group:安裝到系統(tǒng)中的所有APK都具備的組ID。permission:可以指定一個權(quán)限與幾個組ID對應(yīng)。當一個APK被授予這個權(quán)限時,它也同時屬于這幾個組。assign-permission:把一個權(quán)限賦予一個UID,當進程使用這個UID運行時,就具備了這個權(quán)限。library:為系統(tǒng)添加一些擴展庫用的。對應(yīng)的.jar文件放在/system/framework/目錄下。比如GoogleMap相關(guān)的庫。feature:每添加一個硬件,都要增加對應(yīng)的feature。將以上解析的結(jié)果對應(yīng)放入mGlobalGids , mSettings.mPermissions ,mSystemPermissions,mSharedLibraries”mAvailableFeatures等幾個list中供系統(tǒng)查詢和權(quán)限配置使用。}//readLP()會判斷/data/system/packages.xml文件是否存在,如果不存在則返回false,如果存在則進行解析,在系統(tǒng)第一次啟動時packages.xml文件是不存在的,由writeLP()創(chuàng)建該文件,并將該文件寫到nand上,下次開機會直接讀取并解析這個文件。解析的過程即是按照xml定義的標簽,將對應(yīng)的屬性和值添加到全局列表中。packages.xml文件中記錄了系統(tǒng)安裝的所有apk的屬性權(quán)限的信息,當系統(tǒng)中的apk安裝,刪除或升級時,改文件就會被更新。(permissions〉標簽定義了目前系統(tǒng)中定義的所有權(quán)限。 主要分為兩類:系統(tǒng)定義的(package屬性為Android)和APK定義的(package屬性為APK的包名)sharedUserId/userId:Android系統(tǒng)啟動一個普通的APK時,會為這個APK分配一個獨立的UID,這就是userId。如果APK要和系統(tǒng)中其它APK使用相同的UID的話,那就是sharedUserId。perms:APK的AndroidManifest.xml文件中,每使用一個vuses-permission>標簽,vperms>標簽中就會增加一項。vshared-user>代表一個共享UID,通常,共同實現(xiàn)一系列相似功能的APK共享一個UID。<perms>標簽中的權(quán)限代表了這個共享UID的權(quán)限,所有使用的同一個共享UID的APK運行在同一進程中,這個進程的UID就是這個共享UID,這些APK都具有這個共享UID的權(quán)限。name:共享UID的名字,在APK的Android:sharedUserId屬性中使用。userId:使用這個共享UID的所有APK運行時所在的進程的UID。mRestoredSettings=mSettings.readLP();//判斷bootclasspath里的文件(jar文件)是否需要dexopt(判斷標準是檢查DvmGlobals.bootClassPath是否已經(jīng)包含這個文件),如果需要先將文件添加到libFiles里,同時進行dexopt:由Installer通過socket將命令傳給installd的run_dexopt,最終調(diào)用的是/system/bin/dexopt對jar包進行處理。如果已經(jīng)進行了dexopt動作,則將/data/dalvik-cache下的以data開頭的文件刪除,后續(xù)重新建立。如果外部庫mSharedLibraries列表存在,也要檢查列表中的元素是否需要dexopt,如果需要則和bootclasspath進行相同處理。對于/system/framework下apk和jar文件檢查是否需要dexopt.StringbootClassPath=System.getProperty("java.boot.class.path");if(bootClassPath!=null){String]]paths=splitString(bootClassPath,':');for(inti=0;ivpaths.length;i++){try{if(dalvik.system.DexFile.isDexOptNeeded(paths[i])){//是否需要dexoptlibFiles.add(lib);//添加到libFiles列表mInstaller.dexopt(paths[i],Process.SYSTEM_UID,true);//進行dexopt}}}}〃對framework-res.apk不進行dexopt直接添加到libFileslibFiles.add(mFrameworkDir.getPath()+"/framework-res.apk");〃啟動AppDirObserver線程監(jiān)測/system/framework,/system/app,/data/app,/data/app-private幾個目錄的事件,主要監(jiān)聽的是add和remove事件。對于目錄監(jiān)聽底層通過inotify機制實現(xiàn),inotify是在2.6.13中引入的新功能,它為用戶態(tài)監(jiān)視文件系統(tǒng)的變化提供了強大的支持;inotify是一種文件系統(tǒng)的變化通知機制,如文件增加、刪除等事件可以立刻讓用戶態(tài)得知,當監(jiān)測到事件發(fā)生時該線程做何處理呢?MframeworkInstallObserver=newAppDirObserver(mFrameworkDir.getPath(),OBSERVER_EVENTS,true);mFrameworkInstallObserver.startWatching();〃調(diào)用scanDirLI解析以上目錄下的apk文件,該函數(shù)是包管理服務(wù)的重要函數(shù),在后面有詳細的分析privatevoidscanDirLI(Filedir,intflags,intscanMode){String]]files=dir.list();for(i=0;ivfiles.length;i++){Filefile=newFile(dir,files[i]);PackageParser.Packagepkg=scanPackageLI(file,flagslPackageParser.PARSE_MUST_BE_APK,scanMode);if(pkg==null&&(flags&PackageParser.PARSE_IS_SYSTEM)==0&&mLastScanError ==PackageManager.INSTALL_FAILED_INVALID_APK){//Deletetheapkfile.delete();}}}〃對于不存在的systemapk調(diào)用以下函數(shù)刪除掉IteratorvPackageSetting>psit=mSettings.mPackages.values().iterator();PackageSettingps=psit.next();if((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM)!=0&&!mPackages.containsKey()&&!mSettings.mDisabledSysPackages.containsKey()){psit.remove();mInstaller.remove();}〃在解析完以上目錄下的apk后,更新應(yīng)用的權(quán)限updatePermissionsLP(null,null,true,regrantPermissions,regrantPermissions);//writeLP會生成packages.xml和packages.list文件,packages.list的數(shù)據(jù)格式是:pkgName,userId,debugFlag,dataPath(包的數(shù)據(jù)路徑),packages.xml保存了每個已經(jīng)安裝apk的詳盡的信息mSettings.writeLP();以上是包管理服務(wù)在系統(tǒng)啟動時做的全部工作。/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////下面解析其中一個比較重要的函數(shù)scanDirLI:privatevoidscanDirLI(Filedir,intflags,intscanMode){String]]files=dir.list();for(i=0;ivfiles.length;i++){Filefile=newFile(dir,files[i]);PackageParser.Packagepkg=scanPackageLI(file,flagslPackageParser.PARSE_MUST_BE_APK,scanMode);if(pkg==null&&(flags&PackageParser.PARSE_IS_SYSTEM)==0&&mLastScanError ==PackageManager.INSTALL_FAILED_INVALID_APK){

//Deletetheapkfile.delete();這個函數(shù)結(jié)構(gòu)比較簡單,對監(jiān)測的幾個目錄下的每一個apk文件繼續(xù)通過scanPackageLI(file,flagslPackageParser.PARSE_MUST_BE_APK,scanMode)進行解析,對不存在且安裝失敗已經(jīng)無效的非系統(tǒng)apk直接刪除。scanDirLIStringDesTCoDePaH,StringDesTCoDePaH,DisplayMetncsparsePackage(Resourcesres,XmlResourceParserparser,collectCertificatesLI(PackageParserpp,使用PackageSetting緩存的證書ser.使用PackageSetting緩存的證書ser.verifySignaturesLP驗證簽名信息:對于systemimgpkg不進行簽名檢驗,但是1?檢查新安裝的pkg的contentproviders不能與

已經(jīng)安裝的pkg的providers存在沖突2.如果pkg.mAdoptPe^missions,貝U表示該pkg1?對于以”androi命名的包,為其創(chuàng)建/data/system數(shù)據(jù)存儲目錄如果數(shù)據(jù)?普通包貝p創(chuàng)建存在1如果數(shù)據(jù)?普通包貝p創(chuàng)建存在1^Wpkgn^e數(shù)據(jù)存儲1.目錄對應(yīng)的uid與pkg.applicationInfo.uid2?否則,對于systemapp,使用|Jnstaller.remove將其原有數(shù)據(jù)對于non-systemapps以及升級了的systemapps,要調(diào)用cachePackageSharedLibsLI進行處理,即如果該apk存在.so.相等或當前環(huán)境不支持多進程,則直接使用已存的datapath;CachePackageSharedLibsLI解讀:調(diào)用cachePackageSharedLibsForAbiLI查找/lib下的全部.so,并將其父目錄與duct.cpu.abi進行匹配,匹配成功后對除/system/framework外的apk調(diào)用performDexOptLI進行dexopt處理。該函數(shù)先判斷是否需要優(yōu)化處理:判斷條件是forceDex||dalvik.system.DexFile.isDexOptNeeded(path)為true.isDexOptNeeded先判斷gDvm.bootClassPath是否包含該路徑,若包含則不需再優(yōu)化;如果classes.dex存在,則對其將已安裝的application的代碼路徑和pkg結(jié)構(gòu)存到mAppDirs中:mAppDirs.put(pkg.mPath,pkg);//AddthenewsettingtomSettingsmdeiungs.inseriracKagedeiungLr^<gdemng,pKgj;將每個apk的services,providers,receivers,permissions等信息添加至Ueivers等全局列表中。對應(yīng)的mServicesmProvidersmR^為pkgSettings添加新的時間戳:圖2scanDirLI流程分析scanPackageLI是一個重定義函數(shù),它的作用是:用 PackageParser的兩個重定義函數(shù)parsePackage解析package的asset,res,建立asset資源文件路徑;解析AndroidManifest.xml文件,建立PackageParser.Package結(jié)構(gòu),這個結(jié)構(gòu)保存了從AndroidManifest.xml解析出的package的信息。對package進行數(shù)字簽名及完整性校驗,privatePackageParser.PackagescanPackageLI(FilescanFile,intparseFlags,intscanMode){〃實例化一個PackageParser對象PackageParserpp=newPackageParser(scanPath);//parsePackage也是一個重定義函數(shù),它主要做了三件事,一個是解析apk中的asset下的文件,一個是解析res下的文件,關(guān)于asset與res區(qū)別請參考:/hshm20517/archive/2011/06/02/6461890.aspx。然后通過重定義函數(shù)parsePackage(Resourcesres,XmlResourceParserparser,intflags,String]]outError)對apk的AndroidManifest.xml進行解析,將每個標簽對應(yīng)的信息添加到每個包的相關(guān)列表中,如將標簽application下的activity通過pkg.activities.add(a)添加到package的activities列表,將service添加至Uowner.services.add(s)。PackageParser.Packagepkg=pp.parsePackage(scanFile,scanPath,mMetrics,parseFlags);〃檢查這個package是否已經(jīng)存在,以及是否重命名過,以及該系統(tǒng)package是否可以被更新,如果可以被更新,則對比系統(tǒng)分區(qū)和data分區(qū)的package版本,如果系統(tǒng)分區(qū)的package高于data分區(qū)的版本,則保留系統(tǒng)分區(qū)的package〃對package進行簽名認證,如果是systemimg里的,只是通過AndroidManifest.xml獲得簽名,對簽名校驗,不會對全部文件進行有效性檢查;否則,就要結(jié)合META-INF/進行簽名和有效性校驗collectCertificatesLI(pp,ps,pkg,scanFile,parseFlags);〃調(diào)用重定義函數(shù)繼續(xù)進行解析,將每個apk解析出的標簽信息添加到全局的列表里。如將每個apk的recervers列表里的兀素pkg.receivers.get(i),通過mReceivers.addActivity(a,"receiver")添加到全局列表mReceivers里returnscanPackageLI(pkg,parseFlags,scanModeISCAN_UPDATE_SIGNATURE);}<補充知識〉res/raw和assets區(qū)另U*res/raw和assets的相同點:1?兩者目錄下的文件在打包后會原封不動的保存在apk包中,不會被編譯成二進制。*res/raw和assets的不同點:res/raw中的文件會被映射到R.java文件中,訪問的時候直接使用資源ID即R.id.filename;assets文件夾下的文件不會被映射到R.java中,訪問的時候需要AssetManager類。res/raw不可以有目錄結(jié)構(gòu),而assets則可以有目錄結(jié)構(gòu),也就是assets目錄下可以再建立文件夾*讀取文件資源:1.讀取res/raw下的文件資源,通過以下方式獲取輸入流來進行寫操作InputStreamis=getResources().openRawResource(R.id.filename);2?讀取assets下的文件資源,通過以下方式獲取輸入流來進行寫操作AssetManageram=null;am=getAssets();InputStreamis=am.open("filename");(用于內(nèi)置文件但不知道文件名稱,需要篩選出想要的文件然后拷貝到目標目錄中,推薦內(nèi)置在assets文件夾中)res/raw目錄:通過反射的方式得到Rjava里面raw內(nèi)部類里面所有的資源ID的名稱,然后通過名稱獲取資源ID的值來讀取我們想要的文件。assets目錄:getAssets().list("");來獲取assets目錄下所有文件夾和文件的名稱,再通過這些名稱讀取我們想要的文件。另,在處理asset時,android限制最大的數(shù)據(jù)是1M,超出后會報錯誤。</>publicPackageparsePackage(FilesourceFile,StringdestCodePath,DisplayMetricsmetrics,intflags){〃解析/asset下的文件assmgr=newAssetManager();intcookie=assmgr.addAssetPath(mArchiveSourcePath);parser=assmgr.openXmlResourceParser(cookie,"AndroidManifest.xml");〃解析/Res下的文件,通過parsePackage函數(shù)解析AndroidManifest.xml文件Resourcesres=newResources(assmgr,metrics,null);pkg=parsePackage(res,parser,flags,errorText);//設(shè)置代碼路徑和資源路徑pkg.mPath=destCodePath;pkg.mScanPath=mArchiveSourcePath;}PackageparsePackage(Resourcesres,XmlResourceParserparser,intflags,String]]outError){解析AndroidManifest.xml里的各個標簽,并對pkg的mVersionCode,mSharedUserId,mSharedUserLabel,installLocation等變量賦值。對于application,permission-group,permission,permission-tree,uses-permission,uses-configuration,uses-feature,uses-sdk,supports-screens,protected-broadcast,instrumentation,original-package,adopt-permissions,eat-comment等標簽調(diào)用相關(guān)函數(shù)進行處理。解析出每個標簽下的子標簽的信息,然后將這些信息添加到每個package的對應(yīng)列表中,如將application下的activity通過pkg.activities.add(a)添加至Upackage的activities歹U表?!▽kg返回returnpkg;}privatePackageParser.PackagescanPackageLI(PackageParser.Packagepkg,intparseFlags,intscanMode){Checkallsharedlibrariesandmaptotheiractualfilepath.checkpkg.reqFeaturesinmAvailableFeaturesCheckandnoteifwearerenamingfromanoriginalpackagenameCheckifwearerenamingfromanoriginalpackagename.對于originalpackage不是太了解,還需要繼續(xù)研究判斷新裝應(yīng)用的contentproviders是否與已經(jīng)安裝應(yīng)用的產(chǎn)生沖突。if(mPlatformPackage==pkg){//如果包名以android開頭的,則將應(yīng)用的dataDir設(shè)為/data/system//Thesystempackageisspecial.dataPath=newFile(Enviro

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論